I have a list of words inside the JList. Every time I point the mouse cursor at a word, I want the cursor to change into a hand cursor. Now my problem is how to do that?
Could someone help me with this problem?
Use a MouseMotionListener on your JList to detect when the mouse enters it and then call setCursor to convert it into a HAND_CURSOR.
Sample code:
final JList list = new JList(new String[] {"a","b","c"});
list.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
final int x = e.getX();
final int y = e.getY();
// only display a hand if the cursor is over the items
final Rectangle cellBounds = list.getCellBounds(0, list.getModel().getSize() - 1);
if (cellBounds != null && cellBounds.contains(x, y)) {
list.setCursor(new Cursor(Cursor.HAND_CURSOR));
} else {
list.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
#Override
public void mouseDragged(MouseEvent e) {
}
});
You probably want to look at the Component.setCursor method, and use it together with the Cursor.HAND constant.
You can also add MouseListener to the jList (or any ui component). Then implement the methods that mouseEntered, mouseExited
jList.addMouseListener(new MouseListener() {
#Override
public void mouseEntered(MouseEvent e) {
cw.list.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
}
#Override
public void mouseExited(MouseEvent e) {
cw.list.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
Related
I have written a program, which displays a table inside of a JScrollPane. The reason for this is that, if the table gets to long the user should be able to use the scrollbar. Further I want the user to be able to open a popup menu on right click to edit or delete data. At first I thought my implementation works as shown in this image:
Later I realized that if I use the scollbar something gets wrong with the mouseposition and the popup is at the wrong location as shown here:
The mouse is located at the highlighted entry.
Here is my code for this:
table.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()){
rightClickPopUpOnTable(tablePanel.getComponentAt(e.getX(), e.getY()), e.getX(), e.getY());
//rightClickPopUpOnTable(tablePanel.getComponentAt(e.getXOnScreen(), e.getYOnScreen()), e.getXOnScreen(), e.getYOnScreen());
}
}
#Override
public void mouseReleased(MouseEvent e) {
int r = table.rowAtPoint(e.getPoint());
if (r >= 0 && r < table.getRowCount()) {
table.setRowSelectionInterval(r, r);
} else {
table.clearSelection();
}
if (e.isPopupTrigger()){
rightClickPopUpOnTable(tablePanel.getComponentAt(e.getX(), e.getY()), e.getX(), e.getY());
//rightClickPopUpOnTable(tablePanel.getComponentAt(e.getXOnScreen(), e.getYOnScreen()), e.getXOnScreen(), e.getYOnScreen());
}
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
public void rightClickPopUpOnTable(Component component, int x, int y){
JPopupMenu pop = new JPopupMenu();
pop.setVisible(true);
pop.setFocusable(false);
JMenuItem item = new JMenuItem("Edit");
item.addActionListener(new ActionListener() {
#java.lang.Override
public void actionPerformed(ActionEvent e) {
handler.getData().showData(table.getValueAt(table.getSelectedRow(),0).toString());
}
});
JMenuItem item2 = new JMenuItem("Delete");
item2.addActionListener(new ActionListener() {
#java.lang.Override
public void actionPerformed(ActionEvent e) {
int dialogResult = JOptionPane.showConfirmDialog (null, "Are you sure you want to delete "+table.getValueAt(table.getSelectedRow(), 0).toString()+"?","Delete Confirmation",JOptionPane.YES_NO_OPTION);
if(dialogResult == JOptionPane.YES_OPTION){
//DO STUFF
}
}
});
pop.add(item);
pop.add(item2);
pop.show(component, x, y);
}
I found a way to "fix" the problem partially by using e.getXOnScreen() as you can see in the code . Now the popup is displayed at the right location, but it won't highlight the items anymore AND it wont close as shown here:
I would be nice if someone knowns a solution for this.
Kind of a noob question, but then again, I am a noob. I'm trying to implement a sort of "universal" mouse listener. That is, when I click any of the objects on screen, it runs a specific amount of code. I have the current solution below, but the code I want to run is the same for 10 different objects, so this gets rather tedious.
difference2 = new JLabel(new ImageIcon("transparent.png"));
difference2.setBounds(645,490,10,10); //left, top, width, height
contentPane.add(difference2);
difference2.setVisible(true);
difference2.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
//code
}
});
I am aware I can create a separate method such as the following
public void mouseClicked(MouseEvent e) {
JOptionPane.showMessageDialog(null,"this would be nice");
}
But I can't figure out how to set up a mouse listener on every object for it. The JOptionPane currently does nothing.
I might have misread your question, but if you want the same mouselistener on various objects,you could store the instance of your listener in a variable once and then add it to whatever gui object you want it added to.
MouseListener ml = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {//code}
#Override
public void mousePressed(MouseEvent e) {//code}
#Override
public void mouseExited(MouseEvent e) {//code}
#Override
public void mouseEntered(MouseEvent e) {//code}
#Override
public void mouseClicked(MouseEvent e) {//code}
};
JLabel j1 = new JLabel("Label1");
j1.addMouseListener(ml);
JLabel j2 = new JLabel("Label2");
j2.addMouseListener(ml);
You can create an instance of an anonymous class that extends MouseAdapter and assign it to a variable that you can reuse (myMouseListener in this case):
MouseListener myMouseListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
JOptionPane.showMessageDialog(null,"this would be nice");
}
};
difference2.addMouseListener(myMouseListener);
aSecondObject.addMouseListener(myMouseListener);
aThirdObject.addMouseListener(myMouseListener);
...
Excuse me:
I just can't know how to link these successive operation?
Mouse pressed and then drag then release. If an user doesn't do this operation some action won't happen...
Should I add code as the is already pressed to distinguish that?
The constant MOUSE_MOVED doesn't work since Eclipse told me it doesn't know it although I find the parameter in mouse event api
I don't know what's going on... Please help!
Implement a MouseInputListener using a MouseInputAdapter subclass and handle the mousePressed, mouseDragged, and the mouseReleased events.
Take a look at this tutorial for examples.
Here is a simple class that encapsulates the drag detection:
public abstract static class MouseDragListener {
java.awt.Component component;
MouseEvent dragStart;
public MouseDragListener(java.awt.Component component) {
super();
this.component = component;
component.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
dragStart = null;
}
public void mouseDragged(MouseEvent e) {
if (dragStart == null)
dragStart = e;
}
});
component.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (dragStart != null) {
dragReleased(dragStart, e);
}
}
});
}
then to use:
new MouseDragListener(center){
void dragReleased(MouseEvent start,MouseEvent end){
// do something ...
}
}
I developed a program to draw polygon triangles. The triangles were drawn using mouse drag. The coordinate of the triangles were stored in array list. Every times the mouse cursor, mouse over on the existing drawn triangles(within the area of triangle), the mouse cursor should turns to "CROSSHAIR_CURSOR", however this were not happened. Help :-(
...
public class DrawingBoardWithMatrix extends JFrame {
public static void main(String[] args) {
new DrawingBoardWithMatrix();
}
public DrawingBoardWithMatrix(){
this.add(new PaintSurface(), BorderLayout.CENTER);
...
}
private class PaintSurface extends JComponent {
java.util.List<Polygon> triangles = new LinkedList<Polygon>();
Point startDrag, endDrag, midPoint;
Polygon triangle;
public PaintSurface() {
...
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}//end mousePressed
public void mouseReleased(MouseEvent e) {
if (startDrag.x > endDrag.x)
midPoint = new Point((endDrag.x +(Math.abs(startDrag.x - endDrag.x)/2)),e.getY());
else
midPoint = new Point((endDrag.x -(Math.abs(startDrag.x - endDrag.x)/2)),e.getY());
int[] xs = { startDrag.x, endDrag.x, midPoint.x };
int[] ys = { startDrag.y, startDrag.y, midPoint.y };
triangles.add( new Polygon(xs, ys, 3));
startDrag = null;
endDrag = null;
repaint();
}//end mouseReleased
});//end addMouseListener
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}//end mouseDragged
});//end this.addMouseMotionListener
}//end paintSurface
//THIS CODE DOESNT WORK - AND I AM STUCK :-(
public void mouseMoved(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
if (triangles.contains(startDrag))
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
else
setCursor(Cursor.getDefaultCursor());
}// end mouseMoved
private void paintBackground(Graphics2D g2){
...
}
public void paint(Graphics g) {
...
}
}//end private class PaintSurface
}//end public class DrawingBoardMatrix
Do you see the mouseMoved method being invoked at all? The way this is written, the mouseMoved method is a member of PaintSurface, but PaintSurface is not a MouseMotionListener. Implementing 'MouseMotionListener' will force it to implement mouseMoved and mouseDragged. After you have done that, you can add your PaintSurface to itself as a MouseMotionListener. Alternatively, you could move the mouseMoved method inside the MouseMotionAdapter anonymous class that you have already defined:
//paintSurface constructor
....
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}//end mouseDragged
//TRY THIS CODE :-)
public void mouseMoved(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
if (triangles.contains(startDrag))
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
else
setCursor(Cursor.getDefaultCursor());
}// end mouseMoved
});//end this.addMouseMotionListener
}//end paintSurface
EDIT (in response to your comment):
It would appear that your conditional if (triangles.contains(startDrag)) depends on the List<Polygon> finding a Point that considers itself equal to the passed in Point. As far as I can tell from looking at the code in Polygon(it doesnt override the equals method, so it takes the implementation from Object), you will not be able to perform this test 'successfully.' You will need to iterate over your Polygons in your triangles collection and perform a contains operation on each in turn.
EDIT 2:
You are probably over-thinking this a bit. In order to implement the suggestion 'to iterate over your Polygons in your triangles collection...' you could do something like the following:
public void mouseMoved(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
Cursor cursor = Cursor.getDefaultCursor();
//you have a List<Polygon>, so you can use this enhanced for loop
for (Polygon p : triangles) {
if (p.contains(startDrag)) {//Polygon has a 'contains(Point)' method
cursor = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
break; //you've found a hit, break from the loop
}
}
setCursor(cursor);
}// end mouseMoved
You could also consider not setting the cursor with every mouse movement. For that, you can put a test in to check the type of the current cursor and the type of the cursor that your mouse movement is intending to set, and only set it if there is a change:
if (cursor.getType() != getCursor().getType()) {
setCursor(cursor);
}
A JComponent of mine is firing a mouseDragged event too vigorously. When the user is trying to click, it interprets is as a drag even if the mouse has only moved 1 pixel.
How would I add a rule for a particular component that amounted to:
Do not consider it a drag event unless
the mouse has moved 10 pixels from the
point at which is was pressed down.
Note: I know it's not a system setting in my OS, since only events on that component suffer from this over sensitivity.
Thank you.
Previous answers combined together, with proper event type:
public class DragInsensitiveMouseClickListener implements MouseInputListener {
protected static final int MAX_CLICK_DISTANCE = 15;
private final MouseInputListener target;
public MouseEvent pressed;
public DragInsensitiveMouseClickListener(MouseInputListener target) {
this.target = target;
}
#Override
public final void mousePressed(MouseEvent e) {
pressed = e;
target.mousePressed(e);
}
private int getDragDistance(MouseEvent e) {
int distance = 0;
distance += Math.abs(pressed.getXOnScreen() - e.getXOnScreen());
distance += Math.abs(pressed.getYOnScreen() - e.getYOnScreen());
return distance;
}
#Override
public final void mouseReleased(MouseEvent e) {
target.mouseReleased(e);
if (pressed != null) {
if (getDragDistance(e) < MAX_CLICK_DISTANCE) {
MouseEvent clickEvent = new MouseEvent((Component) pressed.getSource(),
MouseEvent.MOUSE_CLICKED, e.getWhen(), pressed.getModifiers(),
pressed.getX(), pressed.getY(), pressed.getXOnScreen(), pressed.getYOnScreen(),
pressed.getClickCount(), pressed.isPopupTrigger(), pressed.getButton());
target.mouseClicked(clickEvent);
}
pressed = null;
}
}
#Override
public void mouseClicked(MouseEvent e) {
//do nothing, handled by pressed/released handlers
}
#Override
public void mouseEntered(MouseEvent e) {
target.mouseEntered(e);
}
#Override
public void mouseExited(MouseEvent e) {
target.mouseExited(e);
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed != null) {
if (getDragDistance(e) < MAX_CLICK_DISTANCE) return; //do not trigger drag yet (distance is in "click" perimeter
pressed = null;
}
target.mouseDragged(e);
}
#Override
public void mouseMoved(MouseEvent e) {
target.mouseMoved(e);
}
}
I've had to do exactly this before. Here's my mouse event processing code, cut down to just the bits relating to making drag require a few pixels before being treated as a drag.
public void mousePressed(int mod, Point loc) {
pressLocation=copyLocation(loc,pressLocation);
dragLocation=null;
}
public void mouseReleased(int mod, Point loc) {
if(pressLocation!=null && dragLocation!=null) {
// Mouse drag reverted to mouse click - not dragged far enough
// action for click
pressLocation=null;
}
else if(dragLocation!=null) {
// action for drag completed
}
else {
// do nothing
}
pressLocation=null;
dragLocation=null;
}
public void mouseDragged(int mod, Point loc) {
if(pressLocation!=null) { // initial drag actions following mouse press
dragLocation=pressLocation; // consider dragging to be from start point
if(Math.abs(loc.x-pressLocation.x)<dragMinimum && Math.abs(loc.y-pressLocation.y)<dragMinimum) {
return; // not dragged far enough to count as drag (yet)
}
// action drag from press location
pressLocation=null;
}
else {
// action drag from last drag location
dragLocation=copyLocation(loc,dragLocation);
}
}
And note, I also had problems with Java some JVM's generating click events after dragging, which I had to detect and suppress.
If I read your question correctly, you're tracking both click and mousedrag events. Can you track the coordinates upon mousedown, followed by a short computation in mousedrag to see if the mouse has moved your desired minimum numbers of pixels? Of course, you then also want to cancel/reset on mouseup or when the mouse is dragged outside the bounds of your JComponent.
Caveat: I haven't done this myself, but I think it's where I'd start if it were me.
Software Monkey's code seemed to be missing some code, so I wrote this solution:
navigationTree.addMouseListener(new DragInsensitiveMouseClickListener(10) {
#Override
public void mouseClicked(MouseEvent e) {
TreePath treePath = navigationTree.getPathForLocation(e.getX(), e.getY());
if(treePath != null) {
processChoice();
}
}
});
This will still fire the mouseClicked() event when the user produces at most 10 pixels of "drag travel".
The code for the click listener:
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DragInsensitiveMouseClickListener extends MouseAdapter {
private final int allowedTravel;
public Point mouseDownPoint;
public DragInsensitiveMouseClickListener(int allowedTravel) {
this.allowedTravel = allowedTravel;
}
#Override
public void mousePressed(MouseEvent e) {
mouseDownPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
double horizontalTravel = Math.abs(mouseDownPoint.getX() - e.getX());
double verticalTravel = Math.abs(mouseDownPoint.getY() - e.getY());
if (horizontalTravel < allowedTravel && verticalTravel < allowedTravel) {
mouseClicked(e);
}
}
}