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);
}
Related
I want to bring back a question that was asked before: java draw line as the mouse is moved
"I would like to add a feature to my application which allows the user to draw a straight line by clicking the mouse at the start location and releasing it at the end location. The line should move as the mouse moves until it is finally released; similar to the way that a line can be drawn using the Microsoft Paint application.
How can implement this so that the line is repainted as it moves without repainting other things that may already be drawn in that rectangular area?"
Question is: How can I draw multiple lines with the old lines still there?
This is the code that works for me, but the previous line gets erased as soon as you draw a new one:
public static void main(String args[]) throws Exception {
JFrame f = new JFrame("Draw a Red Line");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
JPanel p = new JPanel() {
Point pointStart = null;
Point pointEnd = null;
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
});
}
public void paint(Graphics g) {
super.paint(g);
if (pointStart != null) {
g.setColor(Color.RED);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
};
f.add(p);
f.setVisible(true);
}
This is the code that works for me, but the previous line gets erased as soon as you draw a new one:
There are two common approaches:
Keep an ArrayList of objects to paint. Then the paintComponent() method repaints all the objects each time the component needs to repaint itself
Paint onto a BufferImage and then just paint the BufferedImage.
Check out Custom Painting Approaches for a working example of both of these approaches.
Just set in mouseRelesed
pointStart = e.getPoint instead of pointStart = null.
there is no need for any lists or things like that
when you set it to null it starts from the beginning and deletes the last one
Is there a possibility to move window by clicking on one of the panels in the window when that window is undecorated?
I have a main panel with matte border 40 pixels size, and few panels with controls inside, and I would like to move the window when clicking on that border. Is that possible?
You can place another panel over the panel with the border, leaving the border visible.Use the following code to move your window.
public class MotionPanel extends JPanel{
private Point initialClick;
private JFrame parent;
public MotionPanel(final JFrame parent){
this.parent = parent;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
initialClick = e.getPoint();
getComponentAt(initialClick);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
// get location of Window
int thisX = parent.getLocation().x;
int thisY = parent.getLocation().y;
// Determine how much the mouse moved since the initial click
int xMoved = e.getX() - initialClick.x;
int yMoved = e.getY() - initialClick.y;
// Move window to this position
int X = thisX + xMoved;
int Y = thisY + yMoved;
parent.setLocation(X, Y);
}
});
}
}
I've been working with this code for a while now to make a custom titlebar for undecorated windows.
P.S.:You can generalize this example by extending JComponent instead of JPanel.
I have a main panel with matte border 40 pixels size, and few panels with controls inside, and I would like to move the window when clicking on that border
I think that ComponetMover by #camickr is right class for you
Yes, it is very possible. You need a MouseListener to listen on mouse events. you start moving on mousedown and stop moving on mouseup. Then you simply translate the window position by the same amount the mouse translates during that phase (calculate the delta bewteen old mouse position and new mouse position and add that to the frames position). You should be able to do this with a mouse listener fairly easily.
I have a simple solution from my project. Here is my undecorated JDialog class.
public class TimerDialog extends JDialog {
// some fields here
private Point mouseClickPoint; // Will reference to the last pressing (not clicking) position
private TimerDialog() {
initComponents();
addEventsForDragging();
}
private void addEventsForDragging() {
// Here is the code does moving
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseClickPoint = e.getPoint(); // update the position
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Point newPoint = event.getLocationOnScreen();
newPoint.translate(-mouseClickPoint.x, -mouseClickPoint.y); // Moves the point by given values from its location
setLocation(newPoint); // set the new location
}
});
}
private void initComponents() {
setLayout(new FlowLayout());
// adding components
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setAlwaysOnTop(true);
setUndecorated(true);
setResizable(false);
pack();
}
}
int xMoved = (thisX + e.getX()) - (thisX + initialClick.x);
thisX + -thisX = 0
int xMoved = e.getX()-initialClick.x;
What i'm using.
public class MouseLiestenerX implements MouseListener,MouseMotionListener{
private theFrame;
public MouseLiestenerX(Frame theFrame){
this.theFrame = theFrame;
}
private Point startClick;
public void mouseDragged(MouseEvent e) {
int deltaX = e.getX()-startClick.x;
int deltaY = e.getY()-startClick.y;
Core.getSp().setLocation(theFrame.getLocation().x+deltaX, theFrame.getLocation().y+deltaY);
}
public void mousePressed(MouseEvent e) {
startClick = e.getPoint();
}
public void mouseMoved(MouseEvent e){
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
and in your Frame constructor
MouseLiestenerX IMove = new MouseLiestenerX(this);
addMouseListener(IMove);
addMouseMotionListener(IMove);
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));
}
});
Hi
i am trying to add a mouse listener to my frame to get the position of the mouse clicked and check if it is inside the circle, the problem is that it is not triggering
public class CircleDraw extends Frame implements MouseListener {
static int circles = 0;
private double color;
double mousex = 0;
double mousey = 0;
int score;
public void mouseClicked(MouseEvent evt)
{
mousex = evt.getX();
mousey = evt.getY();
}
public void mouseEntered (MouseEvent me) {}
public void mousePressed (MouseEvent me) {}
public void mouseReleased (MouseEvent me) {}
public void mouseExited (MouseEvent me) {}
public void paint(Graphics g) {
try {
this.addMouseListener(this);
while (circles < 20) {
color = 10*Math.random();
Shape circle = new Ellipse2D.Double(900*Math.random(),900*Math.random(), 50.0f, 50.0f);
Graphics2D ga = (Graphics2D)g;
ga.draw(circle);
if(color >2)
ga.setPaint(Color.green);
else
ga.setPaint(Color.BLACK);
ga.fill(circle);
if(circle.contains(mousex, mousey) && color > 2)
score ++;
else
if(circle.contains(mousex, mousey) && color < 2)
score--;
Thread.sleep(1000);
System.out.println(circles);
System.out.println(mousex);
System.out.println(mousey);
circles ++;
ga.setPaint(Color.white);
ga.fill(circle);
}
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
Frame frame = new CircleDraw();
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
frame.setSize(1000, 1000);
frame.setVisible(true);
}}
It is deadly to add your mouselistener in the paint() method, since this method is called very very often (with each repaint), and so many listeners are added (with each repaint).
You should add the listener to your content-panel and not to the JFrame itself. This will do it. You can do this in the constructor of your class:
public CircleDraw() {
this.getContentPane().addMouseListener(this);
}
This won't solve your problem completely I think, since you won't get your mouseclick while your paint-method is active. Your code-design (especially your while-loop) does not give any time to other events to fire. So the mouseclick-event will be handled after your 20 loops. You can check this by adding
public void mouseClicked(MouseEvent evt) {
mousex = evt.getX();
mousey = evt.getY();
System.out.println("X: "+mousex+"/ Y: "+mousey);
}
to your code. You have to run your GUI in a different thread (e.g. use SwingUtilities and a Runnable() therefor). I recommend you to get a good book on JAVA development. Or you can start with online-tutorials like this one.
IMHO you should not try to deal with awt, instead use SWING or SWT for GUI-design, since this is much more compfortable.
add the listener in the constructor, the paint is called repeatedly
Here are some of the problems I see with that source:
Adds the listener in paint()
Calls wait() within the paint() method.
Calls System.exit() within the paint() method (not strictly a problem, but very unusual).
Is poorly formatted and hard to understand
Calls deprecated methods.
Codes in AWT in the wrong millennium.
Should a mouseReleased() event be called when the mouse is released after a mouse is dragged?
I need mouseReleased() to be called to reset some variables used in mouseDragged(), but it never seems to be called.
Check the Oracle tutorial for a simple method to implement both listeners as PaĆlo asks in his comments
Basically (modified from the link above):
//where initialization occurs:
MyListener myListener = new MyListener();
addMouseListener(myListener);
addMouseMotionListener(myListener);
private class MyListener extends MouseInputAdapter {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
// you may not need this method
}
public void mouseDragged(MouseEvent e) {
// do your code
}
public void mouseReleased(MouseEvent e) {
// reset your variables
}