I have simple JTextField and KeyListener.
JTextField textField = new JTextField();
textField.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e)
{
}
#Override
public void keyPressed(KeyEvent e)
{
}
#Override
public void keyReleased(KeyEvent e)
{
validateThatTextWasSelectedWithShiftAndArrow();
}
});
How do I check that someone select text with key combination (SHIFT + LEFT or RIGHT ARROW) ?
Swing makes heavy use of the Key Bindings API to make it easy to work with existing functionality. We already know the JTextField is fully capable of performing selection, we just need to be able to plug into it.
The JTextField uses the selection-backward and selection-forward to execute the required functionality when the system dependent key strokes are activated, we just need to inject our code into it.
For this, I wrote a simple ReplaceAction action, which takes the old Action we are interested, and calls two methods, one before and one after the old Action is called. This allows you to inject your required functionality into whatever point is required to achieve whatever functionality you are trying to implement...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MonitorSelection {
public static void main(String[] args) {
new MonitorSelection();
}
public MonitorSelection() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
JTextField field = new JTextField(10);
add(field);
InputMap im = field.getInputMap(WHEN_FOCUSED);
ActionMap am = field.getActionMap();
Action oldAction = am.get("selection-backward");
am.put("selection-backward", new ReplacedAction(oldAction){
#Override
protected void doAfterReplacedAction() {
System.out.println("Before selection-backward");
}
#Override
protected void doBeforeReplacedAction() {
System.out.println("After selection-backward");
}
});
oldAction = am.get("selection-forward");
am.put("selection-forward", new ReplacedAction(oldAction){
#Override
protected void doAfterReplacedAction() {
System.out.println("Before selection-forward");
}
#Override
protected void doBeforeReplacedAction() {
System.out.println("After selection-forward");
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class ReplacedAction extends AbstractAction {
private Action replaced;
public ReplacedAction(Action replaced) {
this.replaced = replaced;
}
#Override
public void actionPerformed(ActionEvent e) {
doBeforeReplacedAction();
replaced.actionPerformed(e);
doAfterReplacedAction();
}
protected void doBeforeReplacedAction() {
}
protected void doAfterReplacedAction() {
}
}
}
I'm working on an application that allows me to show and hide split planes.
I've read some articles on how to get this but its not what I'm looking for.
here's the code Ive written:
Im currently using netbeans.
private void jSplitPane1MouseEntered(java.awt.event.MouseEvent evt) {
if(MouseInfo.getPointerInfo().getLocation() == jSplitPane1.getLeftComponent().getLocation()){
jSplitPane1.setDividerLocation(100);
System.out.println("Mouse Entered");
}else{
jSplitPane1.setDividerLocation(20);
System.out.println("Mouse Exited");
}
}
I have referred to these posts:
How to make JSplitPane auto expand on mouse hover?
Get Mouse Position
What I want to happen is when I mouse over the left side of the jSplitPane, I would get the divider to extend to 100 as per my first if statement, and when it exists the left side, it contracts back to divider location 20.
This is really, really tricky.
You could use a MouseListener on the "left" component and monitor the mouseEntered and mouseExited events, but these will also get triggered when when you move into and out of a child component which has a MouseListener of it's own (like a JButton).
Okay, you could use a MouseMotionListener on the JSplitPane and monitor for the mouseMoved event and check where the mouse cursor is, but this goes to hell the moment the components (left/right) get their own MouseListener, as the MouseEvents are no longer delivered to the JSplitPane
So, one of the last options you have is to attach a global AWTListener to the event queue and monitor for events which occur on the JSplitPane itself, for example...
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JSplitPane pane = new JSplitPane();
pane.setLeftComponent(makePane(Color.RED));
pane.setRightComponent(makePane(Color.BLUE));
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent me = (MouseEvent) event;
if (pane.getBounds().contains(me.getPoint())) {
System.out.println("Global Motion in the pane...");
me = SwingUtilities.convertMouseEvent(me.getComponent(), me, pane);
Component left = pane.getLeftComponent();
if (left.getBounds().contains(me.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
}
}
}, MouseEvent.MOUSE_MOTION_EVENT_MASK);
// You don't need this, this is to demonstrate
// that mouse events aren't hitting your component
// via the listener
pane.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("Motion in the pane...");
Component left = pane.getLeftComponent();
if (left.getBounds().contains(e.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
});
pane.setDividerLocation(20);
add(pane);
}
protected JPanel makePane(Color background) {
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
pane.setLayout(new GridBagLayout());
pane.add(new JButton("..."));
pane.setBackground(background);
pane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("...");
}
});
return pane;
}
}
}
I would like to show an alert when clicking on the TrayIcon, and show the main window when double clicking on it. I am having issues capturing the double click event: every time I double click, two single click events are fired.
I am using the following code:
trayIcon.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1 && e.getButton() == 1) {
trayIcon.displayMessage(...);
} else if (e.getClickCount() == 2 && e.getButton() == 1) {
frame.setVisible(true);
}
}
});
How can I prevent the single click event stealing the double click ?
This is an imperfect solution to an imperfect problem. By it's very nature, a double click will generate two mouse events, but a double click is any two clicks which occur within a short period of time between each other.
So, you could insert a small delay on the first click, which if triggered, will "assume" that the event is only a single click.
This example uses a Swing Timer set to 300 milliseconds (you could try 250-275, but I found 300 to be just right). When it detects the first click, it starts the timer, if it detects a second click, it stops the timer, otherwise the timer is allowed to execute after the 300 millisecond delay, which assumes a double click...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class JavaApplication314 {
public static void main(String[] args) {
new JavaApplication314();
}
public JavaApplication314() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
public TestPane() {
addMouseListener(new MouseHandler());
label = new JLabel("...");
setLayout(new GridBagLayout());
add(label);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void doOneClick() {
label.setText("One Click");
}
protected void doTwoClicks() {
label.setText("Two Clicks");
}
public class MouseHandler extends MouseAdapter {
private Timer oneClickTimer;
public MouseHandler() {
oneClickTimer = new Timer(300, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
doOneClick();
}
});
oneClickTimer.setRepeats(false);
}
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
oneClickTimer.stop();
doTwoClicks();
} else if (e.getClickCount() == 1) {
oneClickTimer.restart();
}
}
}
}
}
Another option might be would be to use a meta-key (like Alt) to change the state of the menu on a single click
if (e.getClickCount() == 2 && !e.isConsumed()) {
e.consume();
...
}
In my UI i have a JPopMenu with values as ,
for e.g A,B,C
The scenario is,
I opened the JPopupMenu and kept it open.
At back end with a timer running , it updates the content B to some other alphabet at frequent interval.
3.I want the JPopupMenu to get updated while it is kept open.
In current behavior if i close and open JPopupMenu the updated value shows up.
I tried repaint()but it doesn't do anything.
What is the best way to do this?? Am new to swings please help.
Menu items can change their content at run time just fine. Without seeing your code it's hard to tell what you're doing wrong, but here's a working example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class PopupTest {
private static final String[] messages = {
"You are today's 1000th user!",
"You have won an internet!",
"Claim your prize!"
};
private PopupTest() {
JFrame frame = new JFrame("You have won");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lbl = new JLabel("Check your prize!");
frame.setLocationByPlatform(true);
frame.add(lbl);
frame.pack();
final JPopupMenu menu = new JPopupMenu();
final JMenuItem item = new JMenuItem(messages[0]);
menu.add(item);
menu.add(new JMenuItem("Another item that does not work"));
final Timer timer = new Timer(1000, new ActionListener() {
int count;
#Override
public void actionPerformed(ActionEvent e) {
count++;
count %= messages.length;
item.setText(messages[count]);
}
});
menu.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
timer.stop();
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
timer.stop();
}
});
lbl.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
menu.show(e.getComponent(), e.getX(), e.getY());
timer.start();
}
}
});
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new PopupTest();
}
});
}
}
Try to use .revalidate() with .repaint() it might help.
The docs suggest that the revalidate method is called every time something like size changes and manually calling it with repaint seems to solve problems like these.
The software I am working with is written in Java. This particular problem only manifests on Mac, the program functions properly on Windows and Linux.
I basically wrote a custom "tooltip" that follows the mouse around the main window of the application. It is actually a separate, undecorated frame (we will call the "display frame") that changes location based off of mouseMoved events that are received by the window the cursor is moving over. The default location is slightly below and to the right of the cursor, but when it reaches edges of the window it can "flip" to the left side or the top side of the cursor. This works properly on other platforms, as mentioned before, but it appears on the mac that this mouseMoved event is somehow consumed by the display frame, before it ever gets to the main application. So that window is never receiving mouseMoved events, therefore never moving and following the cursor. The only time the display frame changes location, is if the cursor enters it. Then, the main window triggers a mouseExited event, which causes the display frame to setVisible(false) (I don't want to show the display frame if the cursor isn't in the main window). This then triggers a mouseEntered event, which causes the display frame to be redrawn below and to the right, as it is supposed to be.
I have tried setting the focus to the main window when the redraw method is called, and I have printed out .hasFocus() once this is done, and the other window now has focus, but is still not receiving mouseMoved events. Also, putting a mouse listener on the display frame does not work because the mouseMoved events I am interested in are not within the actual frame of the displayFrame, so those are never triggered either.
The very strange part, is there is a way to produce the proper behavior on the mac. Having the display frame follow the mouse around is a certain "Tool Mode" that can be selected within the application. While in this mode the user can also add additional features to the main window. If the user left clicks while in this mode, a small dialog pops up asking you to name the new feature, if you do so and click "Okay", or don't and click "Cancel", now the display frame will follow the mouse around. You can break it again if you move too quickly and manage to get the cursor inside the display frame before it can redraw, and then you're back to square one where it won't follow you around.
The dialog box requires a parent to be set when it is shown, and we thought perhaps it was setting the main window as its parent and that somehow when it came and then left, the mouse events were then passed on to the parent. But, the dialog box is setting its parent to the display frame. So that is sadly not the case either.
This problem occurs on various versions of osx and on different versions of Java. For reference I am running 10.9.2, but it has been replicated on 10.9.3, 10.9.4, and 10.8, 10.6.
I am running Java 1.7.0_51 and 1.7.0_67.
I have spent some time looking online and haven't come up with anything that has really helped and would appreciate any help from here. Below is a much simpler sample program that I wrote that replicates the problem I am experiencing.
Thanks.
package mouseMovedProblem;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.event.MouseInputListener;
public class MainFrame extends JPanel{
public static MainFrame mainFrame;
MainFrame(){
// setOpaque(false);
setBackground(Color.WHITE);
MouseListener ml = new MouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);
}
private class MouseListener implements MouseInputListener{
public void mouseClicked(MouseEvent e) {
// System.out.println("Mouse clicked");
DisplayFrame.showDisplay(e.getX(), e.getY());
String test = JOptionPane.showInputDialog(DisplayFrame.getInstance(),
"This is a test","test");
}
public void mousePressed(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseEntered(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseExited(MouseEvent e) {
DisplayFrame.getInstance().setVisible(false);
}
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
// System.out.println("Mouse moved");
DisplayFrame.showDisplay(e.getX(), e.getY());
}
}
public static MainFrame getInstance(){
if(mainFrame == null){
mainFrame = new MainFrame();
}
Dimension size = new Dimension(900,700);
mainFrame.setPreferredSize(size);
mainFrame.setMinimumSize(size);
return mainFrame;
}
public static void main(String args[]){
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(getInstance(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
class DisplayFrame extends JFrame{
public static DisplayFrame display;
DisplayFrame(){
setUndecorated(true);
JPanel panel1 = new JPanel();
panel1.setBackground(Color.BLACK);
JPanel panel2 = new JPanel();
panel2.setBackground(Color.WHITE);
JTabbedPane tPane = new JTabbedPane();
tPane.setTabPlacement(JTabbedPane.BOTTOM);
tPane.addTab("Black", panel1);
tPane.addTab("White", panel2);
add(tPane);
}
public static DisplayFrame getInstance(){
if(display == null){
display = new DisplayFrame();
}
// Set size
Dimension size = new Dimension(200,200);
display.setPreferredSize(size);
display.setMinimumSize(size);
display.setMaximumSize(size);
return display;
}
public static void showDisplay(int x, int y){
getInstance();
int compX = (int) MainFrame.getInstance().getLocationOnScreen().getX();
int compY = (int) MainFrame.getInstance().getLocationOnScreen().getY();
// Should be the location 10 pixels to the right and 20 pixels below the cursor
int newX = compX+x+10;
int newY = compY+y+20;
// Set location
display.setLocation(newX, newY);
if(!display.isVisible()){
display.setVisible(true);
}
// This is to make sure the frame doesn't get hidden behind the main window
display.toFront();
} // end method
}
Once I corrected your code so it would compile and run, I had no issues with your example...
MacOS X 10.9.4, Java 1.8.0_05.
If there are any other components on the screen which have a registered MouseListener or MouseMoitionListener, they will block events going through to parent components. There is a trick you can use to overcome this is issue, it's a little bit more work, but it does work.
Basically, you can register an AWTListener with the Toolkit masked to deliver MOUSE_MOTION_EVENT_MASK events. This are global, so you will receive ALL mouse motion events that go through the Event Queue, so you will need filter them appropriately, for example...
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MainFrame extends JPanel {
MainFrame() {
// setOpaque(false);
setBackground(Color.WHITE);
MouseListener ml = new MouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
MouseEvent evt = (MouseEvent) event;
Point p = evt.getPoint();
if (evt.getSource() != MainFrame.this) {
p = SwingUtilities.convertPoint(evt.getComponent(), p, MainFrame.this);
}
if (MainFrame.this.getBounds().contains(p)) {
System.out.println(p.x + "x" + p.y);
}
}
}, AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
private class MouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// System.out.println("Mouse clicked");
DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mousePressed(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseEntered(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseExited(MouseEvent e) {
DisplayFrame.getInstance().setVisible(false);
}
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
System.out.println("Mouse moved " + e.getX() + "x" + e.getY());
DisplayFrame.showDisplay(e.getX(), e.getY());
}
}
private static MainFrame mainFrame;
public static MainFrame getInstance() {
if (mainFrame == null) {
mainFrame = new MainFrame();
mainFrame.setLayout(new GridBagLayout());
JPanel blocker = new JPanel();
blocker.setBackground(Color.RED);
blocker.setPreferredSize(new Dimension(200, 200));
MouseAdapter ma = new MouseAdapter() {
};
blocker.addMouseListener(ma);
blocker.addMouseMotionListener(ma);
mainFrame.add(blocker);
Dimension size = new Dimension(900, 700);
mainFrame.setPreferredSize(size);
mainFrame.setMinimumSize(size);
}
return mainFrame;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(getInstance(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
});
}
static class DisplayFrame extends JFrame {
public static DisplayFrame display;
DisplayFrame() {
setUndecorated(true);
JPanel panel1 = new JPanel();
panel1.setBackground(Color.BLACK);
JPanel panel2 = new JPanel();
panel2.setBackground(Color.WHITE);
JTabbedPane tPane = new JTabbedPane();
tPane.setTabPlacement(JTabbedPane.BOTTOM);
tPane.addTab("Black", panel1);
tPane.addTab("White", panel2);
add(tPane);
}
public static DisplayFrame getInstance() {
if (display == null) {
display = new DisplayFrame();
}
// Set size
Dimension size = new Dimension(200, 200);
display.setPreferredSize(size);
display.setMinimumSize(size);
display.setMaximumSize(size);
return display;
}
public static void showDisplay(int x, int y) {
getInstance();
int compX = (int) MainFrame.getInstance().getLocationOnScreen().getX();
int compY = (int) MainFrame.getInstance().getLocationOnScreen().getY();
// Should be the location 10 pixels to the right and 20 pixels below the cursor
int newX = compX + x + 10;
int newY = compY + y + 20;
// Set location
display.setLocation(newX, newY);
if (!display.isVisible()) {
display.setVisible(true);
}
// This is to make sure the frame doesn't get hidden behind the main window
display.toFront();
} // end method
}
}
This example will print the x/y position of the mouse. You will see that when your MouseMoitionListener stops receiving events, the AWTListener containers to print out results.
Updated
I was able to test it using Java 1.7.0_15 and was able to replicate the issue. This seems to be a bug in the Java 7, as even the AWTListener stopped displaying output...
So what's the solution? Upgrade to Java 8...
Okay, if you can't do that, you can use a "hack" work around...basically, you start Thread or javax.swing.Timer which probes java.awt.MouseInfo for the java.awt.PointerInfo and make determinations about the location of the cursor on the screen, for example...
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
SwingUtilities.convertPointFromScreen(p, MainFrame.this);
if (MainFrame.this.getBounds().contains(p)) {
System.out.println("pi = " + p.x + "x" + p.y);
}
}
});
timer.start();
The important thing about this to:
Make sure the mouse pointer is within the confines of your component and
Make sure it has changed before you update anything
As an example...
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MainFrame extends JPanel {
MainFrame() {
// setOpaque(false);
setBackground(Color.WHITE);
MouseListener ml = new MouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
MouseEvent evt = (MouseEvent) event;
Point p = evt.getPoint();
if (evt.getSource() != MainFrame.this) {
p = SwingUtilities.convertPoint(evt.getComponent(), p, MainFrame.this);
}
if (MainFrame.this.getBounds().contains(p)) {
System.out.println(p.x + "x" + p.y);
}
}
}, AWTEvent.MOUSE_MOTION_EVENT_MASK);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
SwingUtilities.convertPointFromScreen(p, MainFrame.this);
if (MainFrame.this.getBounds().contains(p)) {
System.out.println("pi = " + p.x + "x" + p.y);
}
}
});
timer.start();
}
private class MouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// System.out.println("Mouse clicked");
DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mousePressed(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseEntered(MouseEvent e) {
// DisplayFrame.showDisplay(e.getX(), e.getY());
}
public void mouseExited(MouseEvent e) {
DisplayFrame.getInstance().setVisible(false);
}
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
System.out.println("Mouse moved " + e.getX() + "x" + e.getY());
DisplayFrame.showDisplay(e.getX(), e.getY());
}
}
private static MainFrame mainFrame;
public static MainFrame getInstance() {
if (mainFrame == null) {
mainFrame = new MainFrame();
mainFrame.setLayout(new GridBagLayout());
JPanel blocker = new JPanel();
blocker.setBackground(Color.RED);
blocker.setPreferredSize(new Dimension(200, 200));
MouseAdapter ma = new MouseAdapter() {
};
blocker.addMouseListener(ma);
blocker.addMouseMotionListener(ma);
mainFrame.add(blocker);
Dimension size = new Dimension(900, 700);
mainFrame.setPreferredSize(size);
mainFrame.setMinimumSize(size);
}
return mainFrame;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(getInstance(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
});
}
static class DisplayFrame extends JFrame {
public static DisplayFrame display;
DisplayFrame() {
setUndecorated(true);
JPanel panel1 = new JPanel();
panel1.setBackground(Color.BLACK);
JPanel panel2 = new JPanel();
panel2.setBackground(Color.WHITE);
JTabbedPane tPane = new JTabbedPane();
tPane.setTabPlacement(JTabbedPane.BOTTOM);
tPane.addTab("Black", panel1);
tPane.addTab("White", panel2);
add(tPane);
}
public static DisplayFrame getInstance() {
if (display == null) {
display = new DisplayFrame();
}
// Set size
Dimension size = new Dimension(200, 200);
display.setPreferredSize(size);
display.setMinimumSize(size);
display.setMaximumSize(size);
return display;
}
public static void showDisplay(int x, int y) {
getInstance();
int compX = (int) MainFrame.getInstance().getLocationOnScreen().getX();
int compY = (int) MainFrame.getInstance().getLocationOnScreen().getY();
// Should be the location 10 pixels to the right and 20 pixels below the cursor
int newX = compX + x + 10;
int newY = compY + y + 20;
// Set location
display.setLocation(newX, newY);
if (!display.isVisible()) {
display.setVisible(true);
}
// This is to make sure the frame doesn't get hidden behind the main window
display.toFront();
} // end method
}
}