Search code examples
javaswingappletgeometryjapplet

The Marker Won't Change


package CreatingWindows;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.MouseEvent;
public class myCurveApplet extends JApplet{
    @Override
    public void init(){
        this.add(pane);
        pane.addMouseListener(new MouseHandler());
        pane.addMouseMotionListener(new MouseHandler());
    }
    private class CurvePane extends JComponent{
        @Override
        public void paint(Graphics g){
            Graphics2D g2D = (Graphics2D)g;
            if(a!=null&&b!=null&&ctrl!=null){
                System.out.println("Repainted!");
                String text;
                aMark = new Marker(a);
                bMark = new Marker(b);
                ctrlMark = new Marker(ctrl);
                quadCurve = new QuadCurve2D.Double(a.x, a.y, ctrl.x, ctrl.y, b.x, b.y);

                aMark.draw(g);
                g2D.setPaint(Color.BLACK);
                text = "A"+"\n"+"("+a.x+","+a.y+")";
                g2D.drawString(text,(int)a.x,(int)a.y+30);
                bMark.draw(g);
                g2D.setPaint(Color.BLACK);
                text = "B"+"\n"+"("+b.x+","+b.y+")";
                g2D.drawString(text,(int)b.x,(int)b.y+30);
                ctrlMark.draw(g);
                g2D.setPaint(Color.BLACK);
                text = "Control"+"\n"+"("+ctrl.x+","+ctrl.y+")";
                g2D.drawString(text,(int)ctrl.x,(int)ctrl.y+30);

                g2D.setPaint(Color.BLACK);
                g2D.draw(quadCurve);
            }
        }
    }
    private class MouseHandler extends java.awt.event.MouseAdapter{
        @Override
        public void mouseClicked(MouseEvent e){
            if(a==null||b==null||ctrl==null){
                if(a==null){
                    a = new Point2D.Double(e.getX(), e.getY());
                }else if(b==null){
                    b = new Point2D.Double(e.getX(), e.getY());
                }else{
                    ctrl = new Point2D.Double(e.getX(), e.getY());
                }
            }else if(aMark!=null&&bMark!=null&&ctrlMark!=null){
                if(aMark.contains(e.getX(),e.getY())){
                    selectedPoint = a;
                }else if(bMark.contains(e.getX(),e.getY())){
                    selectedPoint = b;
                }else if(ctrlMark.contains(e.getX(),e.getY())){
                    selectedPoint = ctrl;
                }
            }
        }
        @Override
        public void mouseDragged(MouseEvent e){
            if(selectedPoint!=null){
                selectedPoint.x = e.getX();
                selectedPoint.y = e.getY();
            }
        }
        @Override
        public void mouseReleased(MouseEvent e){
            selectedPoint = null;
            pane.repaint();
        }
        private Point2D.Double selectedPoint;
    }
    private class Marker{
        public Marker(Point2D.Double center){
            this.center.setLocation(center);
            circle = new Ellipse2D.Double(center.x,center.y,r,r);
        }
        public void draw(Graphics g){
            Graphics2D g2D = (Graphics2D)g;
            if(circle!=null){
                g2D.setPaint(selectedColor);
                g2D.draw(circle);
            }
        }
        public boolean contains(int x,int y){
            return circle.contains(x, y);
        }
        public void setLocation(int x,int y){
            center.x = x;
            center.y = y;
            circle = new Ellipse2D.Double(center.x,center.y,r,r);
        }
        public Point2D.Double center = new Point2D.Double();
        private Ellipse2D.Double circle;
        private static final double r = 6;
    }

    private Point2D.Double a;
    private Point2D.Double b;
    private Point2D.Double ctrl;
    private QuadCurve2D.Double quadCurve;
    Marker aMark;
    Marker bMark;
    Marker ctrlMark;
    private Color selectedColor = Color.orange;
    private CurvePane pane = new CurvePane();
}

This is the source code to create this:
enter image description here

And the thing here is to allow the user to change the curve by dragging the points across the screen but somehow Im unable to do it. Please tell me what changes to make and why!


Solution

  • There are several problems there.

    The first reason because your program doesn't work it's the following:

    You assign to selectedPoint a copy of an object (a or b or ctrl ). When you modify it inside mouseDragged you are actually modifying the copy of one of those objects (selectedPoint) and not the original one. So when you rebuild the curve:

    quadCurve = new QuadCurve2D.Double(a.x, a.y, ctrl.x, ctrl.y, b.x, b.y);
    

    a b and ctrl have always the same initial values, since you modified only a copy of one of them (selectedPoint).

    To fix this you need to modify directly the desired object. In your case, I'd add a field (es. string name) to your Marker, and I'd save the marker instead of the point. Something like:

    if(aMark!=null&&bMark!=null&&ctrlMark!=null){
         if(aMark.contains(e.getX(),e.getY())){
             selectedMarker = aMark;
         }else if(bMark.contains(e.getX(),e.getY())){
             selectedMarker = bMark;
         }else if(ctrlMark.contains(e.getX(),e.getY())){
             selectedMarker = ctrlMark;
         }
    }
    

    Then when you drag the mouse check which marker is active and change directly the position:

    public void mouseDragged(MouseEvent e){
            if(selectedMarker !=null){
                if (0 == selectedMarker.getName().compareTo("ctrlMark"))
                    ctrl.x = e.getX();
                    ctrl.y = e.getY();
            }
    }
    

    The second reason is that mouseListener and mouseMotionListener uses 2 different instances of MouseHandler. So you have 2 copies of selectedPoint (or better selectedMarker), one used by MouseDragged(mouseMotionListener) and the other used by MouseClicked (MouseListener).

    You could declare selectedMarker as static to solve this problem.


    You have also other mistakes inside your program. Particularly:

    • override paint directly is wrong. Override instead paintComponent and call the base method too: public void paintComponent(Graphics g){super.paintComponent(g);
    • unuseful creation of objects at frametime: you are instancing new objects inside paintComponent method. That's potentially a big overhead. Instance them once, and just modify the needed ones when you actually modify objects coordinates
    • name conventions: use capital letter for classes.

    Here's a working snippet with few fixes:

    import javax.swing.*;
    import java.awt.geom.*;
    import java.awt.*;
    import javax.swing.event.MouseInputAdapter;
    import java.awt.event.MouseEvent;
    public class MyCurveApplet extends JApplet{
         private static Marker selectedMarker;
        @Override
        public void init(){
            this.add(pane);
            pane.addMouseListener(new MouseHandler());
            pane.addMouseMotionListener(new MouseHandler());
        }
        private class CurvePane extends JComponent{
            @Override
            public void paintComponent(Graphics g){
                super.paintComponent(g);
                Graphics2D g2D = (Graphics2D)g;
                if(a!=null&&b!=null&&ctrl!=null){
                    System.out.println("Repainted!");
                    String text;
                    aMark = new Marker(a,"a");
                    bMark = new Marker(b,"b");
                    ctrlMark = new Marker(ctrl,"ctrl");
                    quadCurve = new QuadCurve2D.Double(a.x, a.y, ctrl.x, ctrl.y, b.x, b.y);
    
                    aMark.draw(g);
                    g2D.setPaint(Color.BLACK);
                    text = "A"+"\n"+"("+a.x+","+a.y+")";
                    g2D.drawString(text,(int)a.x,(int)a.y+30);
                    bMark.draw(g);
                    g2D.setPaint(Color.BLACK);
                    text = "B"+"\n"+"("+b.x+","+b.y+")";
                    g2D.drawString(text,(int)b.x,(int)b.y+30);
                    ctrlMark.draw(g);
                    g2D.setPaint(Color.BLACK);
                    text = "Control"+"\n"+"("+ctrl.x+","+ctrl.y+")";
                    g2D.drawString(text,(int)ctrl.x,(int)ctrl.y+30);
    
                    g2D.setPaint(Color.BLACK);
                    g2D.draw(quadCurve);
                }
            }
        }
        private class MouseHandler extends java.awt.event.MouseAdapter{
            @Override
            public void mousePressed(MouseEvent e){
    
                if(a==null||b==null||ctrl==null){
                    System.out.println("FOO");
                    if(a==null){
                        a = new Point2D.Double(e.getX(), e.getY());
                    }else if(b==null){
                        b = new Point2D.Double(e.getX(), e.getY());
                    }else{
                        ctrl = new Point2D.Double(e.getX(), e.getY());
                    }
                }else if(aMark!=null&&bMark!=null&&ctrlMark!=null){
                    if(aMark.contains(e.getX(),e.getY())){
                        System.out.println("SelecteMarker A");
                        selectedMarker = aMark;
                    }else if(bMark.contains(e.getX(),e.getY())){
                        System.out.println("SelecteMarker B");
                        selectedMarker = bMark;
                    }else if(ctrlMark.contains(e.getX(),e.getY())){
                        System.out.println("SelecteMarker CTRL");
                        selectedMarker = ctrlMark;
                    }
                }
            }
            @Override
            public void mouseDragged(MouseEvent e){
                if(selectedMarker!=null){
                    if (0 == selectedMarker.name.compareTo("a")){
                        a.x = e.getX();
                        a.y = e.getY(); 
                    }else if (0 == selectedMarker.name.compareTo("b")){
                        b.x = e.getX();
                        b.y = e.getY();
                    }else if (0 == selectedMarker.name.compareTo("ctrl")){
                        ctrl.x = e.getX();
                        ctrl.y = e.getY();
    
                    }
    
                    pane.repaint();
                }
            }
            @Override
            public void mouseReleased(MouseEvent e){
                System.out.println("SelectedMark NULL");
                selectedMarker = null;
                pane.repaint();
            }
    
        }
        private class Marker{
            public String name;
            public Marker(Point2D.Double center, String name){
                this.name = name;
                this.center.setLocation(center);
                circle = new Ellipse2D.Double(center.x,center.y,r,r);
            }
            public void draw(Graphics g){
                Graphics2D g2D = (Graphics2D)g;
                if(circle!=null){
                    g2D.setPaint(selectedColor);
                    g2D.draw(circle);
                }
            }
            public boolean contains(int x,int y){
                return circle.contains(x, y);
            }
            public void setLocation(int x,int y){
                center.x = x;
                center.y = y;
                circle = new Ellipse2D.Double(center.x,center.y,r,r);
            }
            public Point2D.Double center = new Point2D.Double();
            private Ellipse2D.Double circle;
            private static final double r = 6;
        }
    
        private Point2D.Double a;
        private Point2D.Double b;
        private Point2D.Double ctrl;
        private QuadCurve2D.Double quadCurve;
        Marker aMark;
        Marker bMark;
        Marker ctrlMark;
        private Color selectedColor = Color.orange;
        private CurvePane pane = new CurvePane();
    }