简体   繁体   中英

Java Swing: Is it possible to make a component visible by user but transparent to mouse clicks?

I have an editor project and in the editor panel I have some user resizeble and movable panels. I defined these panels by a seperate class, Resizable.java , which extends JComponent. I am using MouseInputListener, so when user click on Resizable he can move or resize it. When I put a jPanel into it, I can still manage to move/resize it. On the other hand, if I put a JTextArea into Resizable , I cannot operate any more because JTextArea blocking my mouse clicks over Resizable . My intention is that user can edit JTextArea only if he double clicked on it, otherwise he should move/resize the panel. (Like text tool in the adobe flash/photoshop/fireworks)

I have tried to setFocusable(false) for JTextArea but didn't work.

Does anyone know a way to do this? or better implementation?

Sorry for my English, I hope I made myself clear.

Thanks.

You could use a glass pane to capture the mouse events. The Swing Tutotrial has a nice example with a glass pane and mouse events here:

http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html

Another option is to put the JTextArea in a JInternalFrame on a JDesktop . That would allow the users to move and resize it without having to mess with mouse events. It would also be more intuitive of a UI.

My intention is that user can edit JTextArea only if he double clicked on it, otherwise he should move/resize the panel.

When you create the text area you will need to remove the MouseListener and MouseMotionListeners from the text area. Something like:

MouseMotionListener[] mml = (MouseMotionListener[])textArea.getListeners(MouseMotionListener.class);

for (int i = 0; i < actions.length; i++)
    textArea.removeMouseMotionListener( mml[i] );

Then you will need to instal you own custom MouseListener to handle the double click. When you receive a double click event you will then need to remove your MouseListeners and reinstall the default MouseListeners.

Then when you finish editing the text area you need to remove the default listeners and add your custom listener back to the text area.

Finally I have accomplished what I want thanks to jzd. I haven't used glass pane but I wrote an implementation based on the same idea.

First, I created myTextTool class which extends JTextArea and overrides MouseListeners and MouseMotionListeners. I kept a boolean variable, nowEditable , that indicates user trying to edit or move/resize, in the myTextTool class. In the mouselistener methods, I checked nowEditable ; If it is true then make myTextTool editable. If it is false then look for double click. If doubleclick happens then set nowEditable true, else redirect mouseevent to Resizable class.

Here is the code that handles and redirects the mouseevents:

private void redirectMouseEvent(MouseEvent e) {
parentResizable.dispatchEvent(new MouseEvent(parentResizable,
                                                 e.getID(),
                                                 e.getWhen(),
                                                 e.getModifiers(),
                                                 e.getPoint().x+4,
                                                 e.getPoint().y+4,
                                                 e.getClickCount(),
                                                 e.isPopupTrigger()));
}


MouseInputListener ortamListener = new MouseInputAdapter() {
    public void mouseMoved(MouseEvent me) {
        if(!nowEditable)
            redirectMouseEvent(me);
    }

    public void mouseExited(MouseEvent mouseEvent) {
        if(!nowEditable)
            redirectMouseEvent(mouseEvent);
    }

    boolean isAlreadyOneClick=false;
    public void mousePressed(MouseEvent me) {
        //Eğer belirli zaman önce tıklandıysa double click olarak algıla
        if (isAlreadyOneClick && !nowEditable) {
            nowEditable=true;
            setEditable( true );
            getCaret().setVisible(true);        
            isAlreadyOneClick = false;
        }
        //İlk kez tıklandığında ve aktif değilken
        else if(!isAlreadyOneClick && !nowEditable) {
            isAlreadyOneClick = true;
            java.util.Timer t = new java.util.Timer("doubleclickTimer",
                    false);
            //Eğer yarım saniye içinde 2. kez basmaz ise double-click olarak
            //alma
            t.schedule(new java.util.TimerTask() {

                @Override
                public void run() {
                isAlreadyOneClick = false;
                }
            }, 500);

            //Arka kutuya ilet
            redirectMouseEvent(me);
        }
        //Aktifken bir şey yapma

    }

    public void mouseDragged(MouseEvent me) {
        if(!nowEditable)
            redirectMouseEvent(me);
     }

    public void mouseReleased(MouseEvent mouseEvent) {
        if(!nowEditable)
            redirectMouseEvent(mouseEvent);
    }
};

Thanks for all answers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM