Link to home
Start Free TrialLog in
Avatar of AttilaB
AttilaB

asked on

Java: Unable to identify component in focus on JFrame at runtime

I have a JFrame with JTextArea components on it. I will select a particular JTextArea during runtime, and do
various operations such as typing in text, deleting selections, etc. inside each particular text area.

To speed up editing the contents of the JTextArea, I have a pop-up menu I can bring up by moving the mouse away from the JTextArea I am working on right now above the JFrame somewhere, right-click the mouse and select a particular operation I need to do.

See JFrame screen shot:
User generated image
When inside the mouse listener the right-click of the mouse is detected, the JTextArea I was working on still has
the focus, so I should be able to detect the particular JTextArea the pop-up menu actions should be applicable to:

 addMouseListener(new MouseAdapter() // anonymous inner class
           {
                // Mouse press event handler added here:
                public void mousePressed( MouseEvent event )
	           {
	               checkForTriggerEvent(event); // check for trigger
	                   } // end method mousePressed
                // handle mouse release event
	       public void mouseReleased(MouseEvent event)
	       {
	           checkForTriggerEvent(event); // check for trigger
	           } // end method mouseReleased
	           // determine whether event should trigger pop-up menu
	           private void checkForTriggerEvent(MouseEvent event)
	       {
	           if ( event.isPopupTrigger() )
	               editTextAreaPopupMenu.show( event.getComponent(), event.getX(), event.getY() );
                   
                  System.out.println(getJTextAreaNameInFocus());
        } 
    }
); 

Open in new window


Getting the text area name in focus:
// This will determine the last component in focus before popping up the pop-up menu    
    public String getJTextAreaNameInFocus(){
	    Component componentInFocus = this.getFocusOwner();
            System.out.println(componentInFocus.getName());
	         return componentInFocus.getName();
	}
	     

Open in new window


The problem is, that when I run this, the returned Component object doesn't have a name!
(it is null)

See screen-shot of stopping it in the debugger:
User generated image
So how do I find out the name of the control / identify the control in some other way that got the focus?  

(In the past, I have had this same problem about determining the component in focus and got around it by associating a number with each control as part of a scheme when creating them. But that's really convoluted...)
Avatar of AttilaB
AttilaB

ASKER

Just one more note:  Yes, I am sure the component returned by getFocusOwner() is a JTextArea:
User generated image
ASKER CERTIFIED SOLUTION
Avatar of krakatoa
krakatoa
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of AttilaB

ASKER

No I did not.

Just because I did not name it specifically it still had to have a name?  How come it doesn't have that name
returned, that I gave it when creating it?  It must be a different name property then.

But, you are right if I call setname(String) after creating an instance of it, later on getFocusOwner()  will return object that contains that that name property, instead of null.
How come it doesn't have that name returned, that I gave it when creating it?
How are you creating it then? The JTextArea has no other way of setting the "name" other than setName. So I'm not sure what you mean by "that name ... that I gave it"

Can I also ask (just so that you aren't going down the wrong track) what you need the "name" for anyway? To my mind, the actions that are in your popup menu would not have any use for the "name" property.
Just because I did not name it specifically it still had to have a name?  How come it doesn't have that name
returned, that I gave it when creating it?  It must be a different name property then.

Instantiating an Object is different from giving that object a "name". The var you use when instantiating an object is the reference to that object, not a field of that object, which I think is where you got confused.

So :

JTextArea funnyNamedTextArea = new JTextArea();

but then you can do :

funnyNamedTextArea.setName("Regular JTextarea");
Avatar of AttilaB

ASKER

I was not aware of them being separate names. Thanks.
Avatar of AttilaB

ASKER

mccarl, thanks for your comment too. Well, I just need to identify which of the textboxes was active in the final program, because the action I am going to do will in the end be different for the various text areas.

If you look at the returned object, unless you give it a specific property that makes it unique, like the setName(),
there is really no way to tell which one it is, if otherwise they are identical. If they are created as a component array then I could use the array index to identify it. Still it needs to be cross-referenced to a humanly readable word.
That's one more step, one more cross reference. All this just makes the program more complicated.

If you apply the toString() method to the  component object returned, with no name set, you can test it: You cannot tell from that which one it is.
because the action I am going to do will in the end be different for the various text areas.

I guess that is half the question, what IS the difference between the actions for the different text areas?

Still it needs to be cross-referenced to a humanly readable word.
This is the bit that jumps out at me as having the potential to be implemented in possibly a better way. Relying on humanly readable words to link events with the subsequent action (or linking anything in code really) can easily lead to bugs and hard to maintain code. These words might be altered in seemingly insignificant ways, such as adding or removing whitespace or changing case, etc but that end up breaking one of these links between an event and the action that is supposed to follow.

Without knowing what you are doing though it is hard to say if this could be a major issue or not, and it is also hard to give you an idea of better ways of achieving what you want, but I'll try to give you an example...

Say the different action that you want to perform for the different text areas is to show a different popup when right clicked. The way I might solve that is to first define an interface that defines just one method, whose purpose is just to return an object that is a fully constructed popup menu. Then for each text area, you create a class that extends JTextArea but also implements the interface described above and builds and returns an appropriate popup menu for that text area. It extends JTextArea so it can still be added to your GUI just like normal, but then in your right click event handler, you get the component in focus, which while being a (custom) JTextArea will also be an object that implements your interface, so you can the method to retrieve the popup menu, and the appropriate menu will be created and returned, so you just have to display it.

You get the desired result of doing different actions depending on the context, but do don't need to do linking via fragile, human readable strings! I hope the above is easy to understand though, it is a bit of a hard concept to try and describe fully.
Avatar of AttilaB

ASKER

All right. I will certainly consider what you wrote.  I don't have the full app mapped out in my head yet in very high detail, but as I will work on it  I will put up a posting about the structure of it, and if you want you and others could look it over and see if there is another better way. The thing is, that it is very hard to get any detailed spec out of the people that use my code and I do it the best way I can, which is usually NOT good enough for them. (Everything could be done 'differently', always.)
They especially pick at GUI details, because this is what they understand the best. So I try to make my programs as straightforward as possible for myself, so that 6 months or a year from now I can modify them
easily. But, if I can get some sound structural advice I should probably do so and include it as I work on some of the implementation of functionality of my program.

It may only happen in a week or two's time, I need to work on some other projects right now.

Thanks for your note.
I think that what mccarl has said is right, and boils down to not only avoiding error-prone string identification, but also raises the level of abstraction so that calls back to the components become more generic and loosely-coupled, thus more generally useful.

[EDITed out]
The thing is, that it is very hard to get any detailed spec out of the people that use my code and I do it the best way I can, which is usually NOT good enough for them
Yeah, that is pretty much the case 90% of the time, so just think of it as getting experience dealing with difficult people. You'll be better off when the next difficult person comes along! ;)

Good luck with your project!