Solved

How to add pop-up menu for JEditorPane?

Posted on 2001-06-29
12
1,014 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
  • 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

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

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Java DateChooser? 3 36
how to add new optional parameter to JSP 1 40
Desingning Refactoring existing code 2 24
ejb on wildfly 5 19
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

813 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now