Java Challenge on Permitting the User to Draw A Li

2019-09-16 13:21发布

My question has been alluded to in java draw line as the mouse is moved, however, I have not advanced far enough into this book to have covered JPanels, JFrames and Points as stated by the prior programmer who asked this question.

Answering this question definitely would help most beginner programmers better understand the graphics class and drawing, an often intricate process, especially for beginners.

According to the text I am using (as I am learning Java on my own), this was the example of how to draw a line using Java:

/*
 * LineTest
 * Demonstrates drawing lines
 */
import java.awt.*;
public class LineTest extends Canvas {
public LineTest() {
super();
setSize(300, 200);
setBackground(Color.white);
}
public static void main(String args[]) {
LineTest lt = new LineTest();
GUIFrame frame = new GUIFrame("Line Test");
frame.add(lt);
frame.pack();
frame.setVisible(true);
}
public void paint(Graphics g) {
g.drawLine(10, 10, 50, 100);
g.setColor(Color.blue);
g.drawLine(60, 110, 275, 50);
g.setColor(Color.red);
g.drawLine(50, 50, 300, 200);
}
}

The specification is:

Create an application that allows you to draw lines by clicking the initial point and dragging the mouse to the second point. The application should be repainted so that you can see the line changing size and position as you are dragging the mouse. When the mouse button is released, the line is drawn.

As you will recognize, running this program does not create any drawing by the user. I believe this error is encountered due to line 21: g.drawLine(x, y, x2, y2); being incorrect since this is the statement defining the drawing of the line.

Any help is greatly appreciated. Thank you in advance for all your time and cooperation regarding this matter.

My code to answer the question is:

import java.awt.*;
import java.awt.event.*;

public class LineDrawer extends Canvas
                        implements MouseListener, MouseMotionListener {
int x, y, x2, y2;

public LineDrawer() {
    super();
    setSize(300, 200);
    setBackground(Color.white);
}
public void mouseClicked(MouseEvent me) {
                int x = me.getX();
                int y = me.getY();
                int x2 = me.getX();
                int y2 = me.getY();

    }
public void paint(Graphics g) {
            g.drawLine(x, y, x2, y2);
            g.setColor(Color.blue);
    }


    public void mousePressed(MouseEvent me) {
        repaint();
    }

    public void mouseDragged(MouseEvent me) {
    }
    public void mouseExited(MouseEvent me) {
    }
    public void mouseEntered(MouseEvent me) {
    }


    public void mouseReleased(MouseEvent me) {
    }
    public void mouseMoved(MouseEvent me) {
    }

    public static void main(String args[]) {
        LineDrawer ld = new LineDrawer();
        GUIFrame frame = new GUIFrame("Line Drawer");
        frame.add(ld);
        frame.pack();
        frame.setVisible(true);
    }

}

P.S.: I have been hesitant to ask for help since I am concerned that other programmers would answer with methods that I have not yet learned.

2条回答
你好瞎i
2楼-- · 2019-09-16 13:55
int x1, y1, x2, y2;

public void mousePressed(MouseEvent e){
    x1 = e.getX();
    y1 = e.getY();
}

public void mouseDragged(MouseEvent e){
    x2 = e.getX();
    y2 = e.getY();
    // Now Paint the line
    repaint();
}

Hope it helps.

查看更多
姐就是有狂的资本
3楼-- · 2019-09-16 14:13

Let's start with

public void mouseClicked(MouseEvent me) {
    int x = me.getX();
    int y = me.getY();
    int x2 = me.getX();
    int y2 = me.getY();
}

You have previous declared x, y, x2 and y2, but in this method, you have overridden those decelerations with new ones, meaning that the previous declared variables will not be used and the event parameters will be ignored.

mouseClicked is fired AFTER a mousePressed and mouseReleased event, meaning that this is actually when the user has released the mouse button.

Extreme Coder has pointed out that MouseClicked is only fired when the mouse button is pressed and released at the same point, i.e. no dragging is involved - it's still not the right method to use, but the clarification is nice

What you should do is...

On mousePressed store the x, y position of the click and on mouseReleased store the x2, y2 position.

On the mouseDragged event, you should update the x2, y2 values and call repaint

public void mousePressed(MouseEvent me) {
    // Mouse is down, but hasn't yet being released...
    x = me.getX();
    y = me.getY();
    // We need to "override" any previous values...
    x2 = x;
    y2 = y;
    repaint();
}

public void mouseDragged(MouseEvent me) {
    x2 = me.getX();
    y2 = me.getY();
    repaint();
}

public void mouseReleased(MouseEvent me) {
    // Here I would store the points so I could re-draw each new line...
}

Instead of using x, y, x2 and y2, it might be better to use two arrays, ie

private int[] startPoint;
private int[] endPoint;

Then you could do something like...

public void mousePressed(MouseEvent me) {
    // Mouse is down, but hasn't yet being released...
    startPoint = new int[2];
    startPoint[0] = me.getX();
    startPoint[1] = me.getY();
    endPoint = startPoint;
    repaint();
}
public void mouseDragged(MouseEvent me) {
    endPoint = new int[2];
    endPoint[0] = me.getX();
    endPoint[1] = me.getY();
    repaint();
}

Now I prefer paintComponent from JComponent, but I'll stick to you example for now..

public void paint(Graphics g) {
    super.paint(g); // This is super important...
    if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {
        g.drawLine(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
    }
}

Additional

This is of some concern...

public void paint(Graphics g) {
    g.drawLine(x, y, x2, y2);
    g.setColor(Color.blue);
}

The order of operation is VERY important. Setting the color AFTER you've painted the line with have no effect on you paint operations (but may effect paint operations that occur after you).

Also, you MUST call super.paint(g) - this is super important...

Examples

A "basic" example, using int[] arrays for point storage...

public class BasicLineDraw {

    public static void main(String[] args) {
        new BasicLineDraw();
    }

    public BasicLineDraw() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new DrawLinePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DrawLinePane extends JPanel {

        private int[] startPoint;
        private int[] endPoint;
        private List<int[][]> lines;

        public DrawLinePane() {

            lines = new ArrayList<int[][]>(25);

            MouseAdapter handler = new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    startPoint = new int[]{e.getX(), e.getY()};
                    endPoint = startPoint;
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    endPoint = new int[]{e.getX(), e.getY()};
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {
                        lines.add(new int[][]{startPoint, endPoint});
                    }
                    startPoint = null;
                    endPoint = null;
                    repaint();
                }
            };

            addMouseListener(handler);
            addMouseMotionListener(handler);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();
            if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {

                g2d.setColor(Color.RED);
                g2d.drawLine(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);

            }

            g2d.setColor(Color.BLUE);
            for (int[][] line : lines) {
                g2d.drawLine(line[0][0], line[0][1], line[1][0], line[1][1]);
            }

            g2d.dispose();

        }
    }
}

And a more advanced example, using Point and Java's 2D Graphics API

public class LineDrawer {

    public static void main(String[] args) {
        new LineDrawer();
    }

    public LineDrawer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new DrawLinePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DrawLinePane extends JPanel {

        private Point anchor;
        private Point lead;

        private List<Line2D> lines;

        public DrawLinePane() {

            lines = new ArrayList<Line2D>(25);

            MouseAdapter handler = new MouseAdapter() {

                @Override
                public void mousePressed(MouseEvent e) {
                    lead = null;
                    anchor = e.getPoint();
                    repaint();
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    lead = e.getPoint();
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    if (lead != null && anchor != null && !anchor.equals(lead)) {
                        lines.add(new Line2D.Float(anchor, lead));
                    }
                    repaint();
                }

            };

            addMouseListener(handler);
            addMouseMotionListener(handler);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            if (lead != null && anchor != null) {

                Composite composite = g2d.getComposite();
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f));
                g2d.draw(new Line2D.Float(anchor, lead));
                g2d.setComposite(composite);

            }

            for (Line2D line : lines) {
                g2d.draw(line);
            }

            g2d.dispose();

        }

    }

}
查看更多
登录 后发表回答