Solved

How to add pop-up menu for JEditorPane?

Posted on 2001-06-29
12
1,035 Views
Last Modified: 2012-05-04
In Swing, I know that I can use JEditorPane to display a html file. At the same time, some words in the file are allowed to be right-clicked, so that a pop-up menu is displayed for the user to choose.

Now, I decide to add some custom tag to the html file to acheive the above result, so that I can use ElementIterator to get the tag. However, I don't know how to add listener to the words in the html file so that the menu can be displayed.

Moreover, I don't know my above idea is correct or not.

I also want to ask whether there is web site or sample code of this example?

Stephen
0
Comment
Question by:fungho
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
12 Comments
 

Expert Comment

by:kamaljeets
ID: 6237925
hi!
 I am unable to understand how will u be able to add listener to text(listeners can only be added to components),so i think u will be adding listener to JEditorPane.


also have a look at class :

java.awt Class MenuComponent.AccessibleAWTMenuComponent


and class :

javax.accessibility.AccessibleContext


hope this will give u some help if not all

Kamal
0
 

Author Comment

by:fungho
ID: 6238837
Thanks! I do not have time to look at these 2 classes, I will look at them tomorrow. Moreover, I want to know that if I add listener to JEditorPane, could I add different listener to different words?

Thanks!
0
 
LVL 7

Expert Comment

by:Igor Bazarny
ID: 6239180
Hi,

I believe you can't add listener to different words. You need to locate word basing on click position, then show appropriate menu. Check out JTextComponent.viewToModel(). StyledDocument.getParagraphElement, StyledDocument.getCharacterElement() might also help.

Regards,
Igor Bazarny,
Brainbench MVP for Java 1
www.brainbench.com 
0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 

Author Comment

by:fungho
ID: 6240064
Is it useful if I use HTMLEditorKit?
0
 
LVL 7

Expert Comment

by:Igor Bazarny
ID: 6240230
Maybe, if you can turn your sensitive words into hyperlinks. HTMLEditorKit.LinkController class looks promising. Maybe you will need to subclass event delivered to HyperlinkListener. Source digging is necessary to provide more details. I will try to do that tomorrow.
0
 
LVL 7

Accepted Solution

by:
Igor Bazarny earned 200 total points
ID: 6241353
OK. Here is what I able to produce. It seems that JTextPane is repainted too often--there are painting problems.


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.text.html.*;


public class HTMLPopupMenu{          
    private static String content = new StringBuffer()
        .append("<html><body>\n")
        .append("<a href=\"popup:It doest't have to be a valid URL\">\n")
        .append("Right click to see popup menu.</a><br>\n")
        .append("<a href=\"http://www.experts-exchange.com/jsp/qShow.jsp?qid=20143329\">\n")
        .append("You still can handle normal URLs.</a><br>\n")
        .append("And you can have mouse-insensitive text\n")
        .append("</body></html>\n")
        .toString();
    public static void main(String[] args) throws IOException{
        System.out.println(content);
        System.setErr(new PrintStream(new FileOutputStream("err.log")));
        JTextPane textPane = new JTextPane();
        textPane.setEditorKit(new Kit());
        textPane.setText(content);
        textPane.addHyperlinkListener(new LinkListener());
        textPane.setEditable(false);
        JFrame frame = new JFrame("HTML Popup Menu");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(textPane);
        frame.pack();
        frame.setSize(300,300);
        frame.setVisible(true);
    }

    private static class Kit extends HTMLEditorKit{
        private HTMLEditorKit.LinkController linkController;

        public void install(JEditorPane c) {
            super.install(c);
            replaceLinkController(c);
        }

        public void deinstall(JEditorPane c){
            c.removeMouseListener(linkController);
            c.removeMouseMotionListener(linkController);
        }

        void replaceLinkController(JEditorPane c){
            {EventListener[] listeners = c.getListeners(MouseListener.class);
            for( int i=0; i<listeners.length; ++i){
                if(listeners[i] instanceof HTMLEditorKit.LinkController){
                    c.removeMouseListener((MouseListener)listeners[i]);
                }
            }}
            {EventListener[] listeners = c.getListeners(MouseMotionListener.class);
            for( int i=0; i<listeners.length; ++i){
                if(listeners[i] instanceof HTMLEditorKit.LinkController){
                    c.removeMouseMotionListener((MouseMotionListener)listeners[i]);
                }
            }}
            linkController = createLinkController();
            c.addMouseListener(linkController);
            c.addMouseMotionListener(linkController);
        }

        HTMLEditorKit.LinkController createLinkController(){
            return new HTMLPopupMenu.LinkController();
        }

    }
 
    private static class LinkController extends HTMLEditorKit.LinkController{
        public void mousePressed(final MouseEvent event){
            super.mousePressed(event);
            SwingUtilities.invokeLater( new Runnable(){
                public void run(){
                    checkPopup(event);
                }
            });
        }
        public void mouseReleased(MouseEvent event){
            checkPopup(event);
            super.mousePressed(event);
        }
        public void mouseClicked(MouseEvent event){
            checkPopup(event);
            if(isHTMLPane(event.getComponent()) && isPopupHref(getHref(event))){
                return;
            }
            super.mouseClicked(event);
        }

        public void mouseMoved(MouseEvent event){
            if(isHTMLPane(event.getComponent()) && isPopupHref(getHref(event))){
                event.consume();
                return;
            }
            super.mouseMoved(event);
        }

        void checkPopup(MouseEvent event){
            if( !isHTMLPopup(event) ){
                return;
            }
            String href = getHref(event);
            if(isPopupHref(href)){
                event.consume();
                showPopup(event,href);
            }
        }
       
        boolean isHTMLPopup(MouseEvent event){
            return event.isPopupTrigger()
                && isHTMLPane(event.getComponent());
        }
                                 
        boolean isHTMLPane(Component component){
            return component instanceof JEditorPane
                && ((JEditorPane)component)
                    .getDocument() instanceof HTMLDocument;
        }

        String getHref(MouseEvent event){
            JEditorPane editor = (JEditorPane)event.getSource();
            HTMLDocument doc = (HTMLDocument)editor.getDocument();

            Point pt = new Point(event.getX(), event.getY());
            Element e = doc.getCharacterElement(editor.viewToModel(pt));
            AttributeSet a = e.getAttributes();
            AttributeSet anchor = (AttributeSet) a.getAttribute(HTML.Tag.A);
            return (anchor == null ? null
                : (String) anchor.getAttribute(HTML.Attribute.HREF) );
        }

        boolean isPopupHref(String href){
            return href != null && href.startsWith("popup:");
        }

        void showPopup(MouseEvent reason, String targetHref){
            JPopupMenu popup = new JPopupMenu();
            popup.add("Item 1");
            popup.add("Item 2");
            popup.show(reason.getComponent(),reason.getX(),reason.getY());
        }
    }

    private static class LinkListener implements HyperlinkListener{
        public void hyperlinkUpdate(HyperlinkEvent e) {
            JEditorPane pane = (JEditorPane) e.getSource();
            try {
                pane.setPage(e.getURL());
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }
}                        
0
 

Author Comment

by:fungho
ID: 6242951
Thanks! It works!
I want to ask whether I can add scroll bar to the textpane?
0
 

Author Comment

by:fungho
ID: 6243809
I met a serious problem when I try to add the listener to the pop up menu. It said that Popup.LinkController cannot use addMouseListener or addPopupMenuListener... how to solve this?
Then how can I add listener to different element in the pop up menu?
0
 
LVL 7

Expert Comment

by:Igor Bazarny
ID: 6243811
> I want to ask whether I can add scroll bar to the textpane?
Just put it into JScrollPane.

BTW, what java version did you use? My code has rather big painting problem on 1.3.1/Win98.

Regards,
Igor Bazarny.

P.S. BTW, would you mind awarding points?
0
 
LVL 7

Expert Comment

by:Igor Bazarny
ID: 6243862
Well, in place where you create menu you can add listeners to items

JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Item 1");
item.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent event){
        System.out.println("Popup menu item selected!!!");
    }
});
popup.add(item);
popup.add("Item 2");
popup.show(reason.getComponent(),reason.getX(),reason.getY());
0
 

Author Comment

by:fungho
ID: 6243931
bazarny, don't worry, i must give it to you! thanks for ur answer. I will try to test it later and ensure it is ok! Thanks!
0
 

Author Comment

by:fungho
ID: 6243943
Thanks for the code and the answer! I still have some questions in fact, hope you can help me later... I increase the point to 200 to thanks you!

Stephen
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Java: anonymous class 4 54
glassfish admin console 1 47
jmeter usage 4 61
How to find out if all executorservice threads have finished 2 12
After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question