-1

I basically wanna make a single window application where the user will be able to draw segment lines. The application flow should be:

  1. The user clicks the unique button of the app in order to start the process
  2. The user selects by clicking the first point of the segment
  3. The user selects by clicking the second point of the segment

I already have the following piece of code:

public class LineEditor extends JComponent{

        private class Point{
            int x, y;

            public Point(int x, int y){
                this.x = x;
                this.y = y;
            }
        }
        private class Line{
            Point a, b;

            public Line(Point a, Point b){
                this.a = a;
                this.b = b;
            }
        }

        private ArrayList<Line> lines = new ArrayList<Line>();

        public void setLine(Point a, Point b){
            lines.add(new Line(a, b));
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Line line : lines) {
                g.setColor(line.color);
                g.drawLine(line.a.x, line.a.y, line.b.x, line.b.y);
            }
        }

        public static void main(String[] args){
            int height = 500, width = 500;

            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // Properties of the main window
            frame.setAlwaysOnTop(true);
            final LineEditor lineEditor = new LineEditor();
            lineEditor.setPreferredSize(new Dimension(width, height));

            JPanel panelCanvas = new JPanel(); 
            panelCanvas.setPreferredSize(new Dimension(width, height));


            JPanel secondaryPanel = new JPanel();
            JButton addLineButton = new JButton("Add new line");
            secondaryPanel.add(addLineButton);


            frame.getContentPane().add(lineEditor, BorderLayout.CENTER);
            frame.getContentPane().add(panelCanvas, BorderLayout.CENTER);
            frame.getContentPane().add(secondaryPanel, BorderLayout.NORTH);

            panelCanvas.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    int x = e.getX();
                    int y = e.getY();
                }
            });

            addLineButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    // x
                }
            });

            frame.pack();
            frame.setVisible(true);

        }
    }

I don't get how to:

  1. Activate the panelCanvas.addMouseListener only after the user has pressed the button.
  2. Get the mouse coordinates (after the click has been made) from the addLineButton.addActionListener so I can create two Point objects and after that make a call to lineEditor.setLine(pointA, pointB)

I wanna achieve something like:

addLineButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {

        // Wait for the first user click
        int x1 = mouseListener.getX();
        int y1 = mouseListener.getY();
        Point a = new Point(x1, y1);

        // Wait for the second user click
        int x2 = mouseListener.getX();
        int y2 = mouseListener.getY();
        Point b = new Point(x2, y2);

        lineEditor.setLine(a, b);
    }
});
Erwol
  • 1,911
  • 2
  • 23
  • 28
  • What you might need is some kind of model which the `panelCanvas`'s `MouseListener` can update and from which the `addLineButton`'s `ActionListener` can read from. Personally, I think you might have it backwards, what should happen is the use should select "draw line", then click on the canvas the points they want to draw between. Again, much of this would be controlled by some kind of model – MadProgrammer Jan 16 '17 at 19:37
  • An example is cited [here](http://stackoverflow.com/a/11944233/230513). – trashgod Jan 17 '17 at 11:12
  • @trashgod that example was not related to what I was looking for but still is an interesting sample to have in mind. – Erwol Jan 31 '17 at 21:17
  • @MadProgrammer, I finally solved this problem in a really simple way; just by implementing a mouse listener with various methods. I've posted the answer in case someone find it useful. – Erwol Jan 31 '17 at 21:17

1 Answers1

0

I finally solved the problem by forcing the user to follow the next flow when drawing a new line:

  1. When the user firsts try to click on the first point of the line, a JColor box is opened so the line colour can be easily selected.
  2. Then, the user has to click on the first point where he wants to set the first point of the line.
  3. The second point of the line will be located in the coordinates where the user releases the click button.

Note that this's just an approach to what I was looking for (first click&release=first point, second click&release=second point), but still I think it could be a nice sample for swing beginners.

public class LineEditor extends JComponent{

    private static class Point{
        final int x, y;

        public Point(int x, int y){
            this.x = x;
            this.y = y;
        }
    }
    private static class Line{
        final Point a, b;  
        final Color color;

        public Line(Point a, Point b, Color color) {
            this.a = a;
            this.b = b;
            this.color = color;
        }               
    }

    private final LinkedList<Line> lines = new LinkedList<Line>();

    public void addLine(int xa, int ya, int xb, int yb, Color color) {
        lines.add(new Line(new Point(xa, ya), new Point(xb, yb), color));        
        repaint();
    }

    public void clearScreen() {
        if(lines.size() > 0){
            lines.remove(lines.getLast());
            repaint();
        }   
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Line line : lines) {
            g.setColor(line.color);
            g.drawLine(line.a.x, line.a.y, line.b.x, line.b.y);
        }
    }

    public static void main(String[] args) {
        int width, height;
        width = 500;
        height = 500;

        JFrame backgroundFrame = new JFrame();
        backgroundFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final LineEditor lineEditor = new LineEditor();
        lineEditor.setPreferredSize(new Dimension(width, height));
        backgroundFrame.getContentPane().add(lineEditor, BorderLayout.CENTER);

        JPanel buttonsPanel = new JPanel();
            JButton clearScreen = new JButton("Remove last line");
            buttonsPanel.add(clearScreen);
            backgroundFrame.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);

        backgroundFrame.addMouseListener(new MouseAdapter() {
            int ax, ay, bx, by;
            Color color;
            Boolean colorSetted = false;
            @Override
            public void mouseEntered(MouseEvent e) {
                if(!colorSetted){
                    JColorChooser colorChooser =new JColorChooser();
                    this.color = colorChooser.showDialog(null, "Select a color", Color.BLACK);
                    colorSetted = true;
                }
            }
            @Override
            public void mousePressed(MouseEvent e) {
                ax = e.getX();
                ay = e.getY();
                System.out.println("Mouse pressed: " + ax + ", " + ay);


            }

            @Override
            public void mouseReleased(MouseEvent e) {
                bx = e.getX();
                by = e.getY();
                System.out.println("Mouse released: " + bx + ", " + by);
                lineEditor.addLine(ax, ay, bx, by, color);
                colorSetted = false;
            }
        });

        clearScreen.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                lineEditor.clearScreen();
            }
        });

        backgroundFrame.pack();
        backgroundFrame.setVisible(true);
    }
}
Erwol
  • 1,911
  • 2
  • 23
  • 28