Right click focus in Swing - java

Today in my Swing app when I left click, the text area gets focused. When I do a right click on any other text field,the popup menu appears but that text area is not focused. The focus remains on the field left clicked on before. How do I remove the focus from the previous field and make it appear on the field that is right clicked upon ?
if (e.isPopupTrigger()) {
ContextMenu menu = new ContextMenu();
menu.show(tree, e.getX(), e.getY());
}
Doing this on mouseRelease.

Assuming you meant 'focus' instead of 'highlight':
Create a subclass of JTextField, add a mouse listener and force the text field to request focus whenever the mouse button is pressed, released or clicked (three versions to make sure it works on every platform).
import javax.swing.JTextField;
public class TextFieldRClick extends JTextField {
public TextFieldRClick() {
super();
createMouseListener();
}
public TextFieldRClick(int cols) {
super(cols);
createMouseListener();
}
private void createMouseListener() {
this.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mousePressed(java.awt.event.MouseEvent evt) {
requestFocusInWindow();
}
#Override
public void mouseReleased(java.awt.event.MouseEvent evt) {
requestFocusInWindow();
}
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
requestFocusInWindow();
}
});
}
}
You can then create text fields as directly 'new TextFieldRClick()' giving them the ability to get the focus when the user right-clicks them.
I had the same problem, this solved it for me.
EDIT: Changed requestFocus() to requestFocusInWindow(). requestFocus() is said to be platform dependent and should no longer be used.

Related

Drawing Swing components inside a Graphics object

is there any way I can make a Java Graphics object (g) draw a swing component?
like a button or JLabel
something like g.drawJLabel ?
I'm trying to add a clickable text (Link) inside my graphic object but it's not possible to add a mouse listener to the graphics objects
Your clickable text can be an JLabel with an mouselistener
JLabel hyperlink=new JLabel("Click me");
hyperlink.addMouseListener(new MouseAdapter()
{
#Override
public void mouseEntered(MouseEvent m)
{
hyperlink.setForeground(Color.blue);
}
#Override
public void mouseExited(MouseEvent m)
{
hyperlink.setForeground(Color.black);
}
#Override
public void mouseClicked(MouseEvent m)
{
if (Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
Desktop.getDesktop().browse(new URI(hyperlink.getText())));
}
}
Make sure that your graphical object has some form of layout manager otherwise your text won't show up
Then inside your graphical objects which I assume all of them extends some form of JComponent you can add this text to your object and your text will still receive user input

Why Listeners are interdependent on one another in Java?

I have written MineSweeper game. In that I have two Listeners for a button as,
class SampleClass extends MouseAdapter implements ActionListener {
//Some code here
public void actionPerformed(ActionEvent event){ // Buttons listener..
System.out.println("I came here to actionPerformed.");
//Some Code
}
public void mouseClicked(MouseEvent event) { //Mouse listener..
System.out.println("I came here to MouseClicked.");
//Some Code
if(event.getButton() == MouseEvent.BUTTON3){..}//If Right Mouse Button Is Clicked!!
else if(event.getButton() == MouseEvent.BUTTON1){..}//If Left Mouse Button Is Clicked!!
}
}
What I observed is , whenever left button of mouse is clicked, the only actionPerformed is called and not mouseClicked. But on the click of the right button of mouse, mouseClicked is called ( and as in normal case , actionPerformed is not called).
But, When I remove the ActionListener, then on both clicks of left and right mouse buttons mouseClicked is called and works perfectly fine.
I thought, the two listeners to be two different independent threads, listening for the events, But why one depends on other?
No two listeners are not dependent on each other. It is the property of JButton to fire an Action if it is pressed, either by space bar , or calling doClick or by left click of mouse. That's why actionperformed is called by default(given that the ActionListener is registered with it) when you press the JButton by left click of mouse but before actionPerformed is called , mousePressed event is called. And in case the ActionListener is not registered with the JButton , MouseEvent comes into play and the required action is performed. Two Listeners work independently of each other. In fact actions are fired in a proper sequence.. for Example for JButton if ActionListener and MouseListener both are registered .. Then the sequence of actions fired is as follows:
mousePressed()
actionPerformed()
mouseReleased()
mouseClicked()
This code would make you clear about these points.:
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
class Listeners extends JFrame
{
public void prepareAndShowGUI()
{
setTitle("Listeners dependency");
JButton button = new JButton("Click");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent evt)
{
System.out.println("Action Listener has listened.");
}
});
button.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
System.out.println("Mouse Clicked.");
}
public void mousePressed(MouseEvent evt)
{
System.out.println("Mouse pressed.");
}
public void mouseReleased(MouseEvent evt)
{
System.out.println("Mouse Released.");
}
});
getContentPane().add(button);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String stp[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Listeners listen = new Listeners();
listen.prepareAndShowGUI();
}
});
}
}
on Clicking the JButton following output is obtained:
Mouse pressed.
Action Listener has listened.
Mouse Released.
Mouse Clicked.
AWT's MouseListener and MouseMotionListener handling acts very strange sometime.
But as what I think events should not interfere with each other.
If a component has no mouse listener
then mouse events are raised up to the parent container. This means you
can get away with listening to a parent component, and still receive
events for all of its children.In the above usecase which if some other code adds a mouse listener to a child component than mouse events will not bubble up to parent container.
This is really a bad design.
I prefer to use mouse listener if and only if I am writing a subclass of a JComponent or a PL&F because they can get overidden by other events listeners.So i guess this is what happened in your case.And one suggestion is to use EventQueue that should serve your purpose.

How to stop JButton being enabled when mouse hovers over it?

I created a frame using NetBeans. The frame has two buttons A and B. Button A is initially disabled. It is to be enabled only when button B is clicked.
public newFrame() { //newFrame is the name of the frame that has buttons A&B
initComponents();
btn_A.disable();
}
private void btn_BActionPerformed(java.awt.event.ActionEvent evt)
{
btn_A.enable();
}
The problem is that button A becomes active/enabled when the mouse is moved over it ie inspite of whether button B is clicked or not. How can i fix this?
I want button A to be enabled only after button B is clicked and not as a result of any other event.
Use btn_A.setEnabled(false) instead of btn_A.disable()
btn_A.enable() is a deprecated method.
To do this task, you could replace it by btn_A.setEnabled(false); to disable the button and btn_A.setEnabled(true); to enable the button.
Also, one more suggestion is, add statements like the following in your method if you feel something wrong happening:
System.out.println("Some statement relevant to the method");
The main aim of those extra statements being you know when the method was actually executed.
Try the following code:
button. addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
button.setEnable(true);
}
public void mouseExited(MouseEvent me) {
button.setEnable(false);
}
});

JDateChooser : MouseClicked event doesn't get fired

I want to double click on a JDateChooser to make it enabled. So I use a MouseListener :
jDateChooser1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
System.out.println("mouse clicked");
}
});
But this event doesn't get fired, nothing happend.
The date chooser is the com.toedter.calendar one :
Any suggestion ?
Solution
The JDateChooser is a Panel, and I have to listen to a mouse event from on component in the panel. JDateChooser has a getDateEditor(), witch is the textfield.
Here is the solution :
this.jDateChooser1.getDateEditor().getUiComponent().addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
if(evt.getClickCount()==2){
Component c = ((Component)evt.getSource()).getParent();
c.setEnabled(!c.isEnabled());
}
}
});
The class JDateChooser extends JPanel. I guess that the area where you are clicking is found inside another Container that is added to the root JPanel. You should try to identify which Container is the one that fires the events and add the listener to it.
to test if this is correct, try to recursively add the listener to all containers and if you see that it gets fired, you can remove the recrusive setting of listeners and try to locate which one of them you need to add the MouseListener to. (Note i write the code directly without testing so please fix any mistake)
private void addMouseListenerRecrusively(Container container){
for (Component component:container.getComponents()){
if (component instanceof Container)
addMouseListenerRecrusively(component);
}
container.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
System.out.println("mouse clicked");
}
});
}
and call the method on your chooser
addMouseListenerRecrusively(jDateChooser1);

How can I create a "Drop-Down" menu in a Java Swing toolbar?

I've created a drop-down menu on my Swing JToolBar. But it doesn't create behave the way I want. I'm aiming for it to work like Firefox's "Smart Bookmarks" button.
It disappears when the user selects a menu item: CORRECT!
It disappears when the user presses ESC: CORRECT!
It disappears when the user clicks somewhere in the main frame outside of the menu: CORRECT!
But it doesn't disappear when the user clicks a second time on the button that shows the drop-down menu: INCORRECT... :-(
My question is how can I add this behaviour, that it does disappear when the clicks on the button that shows the menu a second time.
Here's my current code, from Java 6 on the Mac:
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
public class ScratchSpace {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Toolbar with Popup Menu demo");
final JToolBar toolBar = new JToolBar();
toolBar.add(createMoreButton());
final JPanel panel = new JPanel(new BorderLayout());
panel.add(toolBar, BorderLayout.NORTH);
panel.setPreferredSize(new Dimension(600, 400));
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private static AbstractButton createMoreButton() {
final JToggleButton moreButton = new JToggleButton("More...");
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
moreButton.setFocusable(false);
moreButton.setHorizontalTextPosition(SwingConstants.LEADING);
return moreButton;
}
private static void createAndShowMenu(final JComponent component, final AbstractButton moreButton) {
JPopupMenu menu = new JPopupMenu();
menu.add(new JMenuItem("Black"));
menu.add(new JMenuItem("Red"));
menu.addPopupMenuListener(new PopupMenuListener() {
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
moreButton.setSelected(false);
}
public void popupMenuCanceled(PopupMenuEvent e) {
moreButton.setSelected(false);
}
});
menu.show(component, 0, component.getHeight());
}
}
Well, here is a potential solution that is not without it's drawbacks. Only you can decide if this is acceptable for your application. The issue is that the popup closing occurs before other mouse-handling events are fired so clicking on your More.. button again causes the popup to hide, thus resetting the buttons state to deselected BEFORE the button even gets told it was pressed.
The easy workaround is to add the following call within your main program:
UIManager.put("PopupMenu.consumeEventOnClose", Boolean.TRUE);
The result of this is that whenever a popup menu is closed because of a mouse-pressed event, that mouse event will be consumed at the time the menu is closed and won't be passed on to any other components under the mouse. If you can live with limitation, this is an easy solution.
What's happening is that when you click off the menu, it cancels the popup menu, so you deselect the button, but the next immediate event is clicking the button, and now its deselected so it shows the menu again.
I don't have the exact solution yet, but give me a little bit ...
I don't use Firefox so I don't know what the Smart Bookmarks button looks like, but maybe use a JMenu as the "button". You could try using the Border of a JButton to make it look more like a button.
Well, the listener on the button reacts only when it is pushed down, because you listen for ItemEvent.SELECTED events only. How about adding another if clause to listen for ItemEvent.DESELECTED events here:
moreButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
createAndShowMenu((JComponent) e.getSource(), moreButton);
}
}
});
You could either store a reference to the menu somewhere, or you could make the menu itself add another listener to the button. The latter solution could be more straightforward, since you already seem to send a button reference to the menu.

Categories