0

I have tried and tried, I looked up many examples for keeping Shapes on the screen but can't seem to adapt to my code. In Summary, a left click prints a square, a right click prints a circle. I would like to fill the window with squares (rects) and circles. Any help and explanation so I can learn the concept would be great. I understand I have to keep track on the coordinates, perhaps in a loop but can seem to get it to work. Thanks again.

import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

public class MouseButtonTester extends JFrame implements MouseListener
{
    private int mouseX, mouseY;
    private int mouseButton;
    private boolean isFirstRun;
    private static final int WIDTH = 640;
    private static final int HEIGHT = 480;
    private static final long serialVersionUID = 0;  //use this if you do not like warnings

    public MouseButtonTester() //constructor
    {
        super("Mouse Button Tester");

        //set up all variables
        mouseX = mouseY = 0;
        mouseButton = 0;
        isFirstRun = true;

        //set up the Frame
        setSize(WIDTH,HEIGHT);
        setBackground(Color.WHITE);
        setVisible(true);

        //start trapping for mouse clicks
        addMouseListener(this);
    }

    public void mouseClicked(MouseEvent e)
    {
        mouseX=e.getX();  //Tracks x coordinates
        mouseY=e.getY();  //Tracker y coordinates

        mouseButton = e.getButton(); //gets button number



           repaint();


    }

    public void paint( Graphics window ) // Draws the Window
    {
        if(isFirstRun)
        {
            window.setColor(Color.WHITE);
            window.fillRect(0,0,WIDTH, HEIGHT);

            //change isFirstRun

        }

        window.setFont(new Font("TAHOMA",Font.BOLD,12));
        window.setColor(Color.BLUE);
        window.drawString("MOUSE BUTTON TESTER", 420,55);

        draw(window);


    }

    public void draw(Graphics window)
    {
        if(mouseButton==MouseEvent.BUTTON1)     //left mouse button pressed
        {
            //window.drawString("BUTTON1", 50,200);  //debug code
            window.setColor(Color.RED);
            window.drawRect(mouseX,mouseY,10,10);



        }
        //right mouse button pressed
        {
            if (mouseButton == MouseEvent.BUTTON2)

                window.setColor(Color.BLUE);
            window.drawOval(mouseX,mouseY,10,10);


        }


        //any other mouse button pressed
        {



        }
    }




    public void mouseEntered(MouseEvent e) { }
    public void mouseExited(MouseEvent e) { }
    public void mousePressed(MouseEvent e) {
    }
    public void mouseReleased(MouseEvent e) { }
}

------ Main Method --------------
public class MouseButtonTesterRunner
 {
     public static void main(String[] args)


     { MouseButtonTester prog = new MouseButtonTester();




     }


 }
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
dontay
  • 9
  • 1
  • 3
    Keep a list where you have clicked with the left or right mouse button and inside your `paint()`/`draw()` method you read this list and paint circles/squares. – Progman Mar 12 '20 at 21:22
  • The if-else branching in the draw method probably does not do what you expect. The brackets are misplaced. The second `if` statement applies only to `window.setColor` while `window.drawOval` is called every time. – Antimonit Mar 12 '20 at 21:50

3 Answers3

1

First, start by having a read through:

So you can get a understanding how painting in Swing works, how you can work with it and your responsibilities when doing so.

Next, have a read through:

for reasons why you should avoid overriding paint of top level containers like JFrame

Finally...

Painting in Swing is destructive, that is, every time your component is painted, you are expected to completely repaint the component state from scratch.

In order to achieve your goal, you will need to maintain a cache of the items you want to paint.

The concept itself it's very difficult, but there might be some "gotchas" along the way

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> circles;
        private List<Point> squares;

        public TestPane() {
            circles = new ArrayList<>();
            squares = new ArrayList<>();

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseReleased(MouseEvent e) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        circles.add(e.getPoint());
                    } else if (SwingUtilities.isRightMouseButton(e)) {
                        squares.add(e.getPoint());
                    }
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // I'm picky
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.RED);
            for (Point p : circles) {
                g2d.drawOval(p.x, p.y, 10, 10);
            }
            g2d.setColor(Color.BLUE);
            for (Point p : squares) {
                g2d.drawRect(p.x, p.y, 10, 10);
            }

            g2d.setFont(new Font("TAHOMA", Font.BOLD, 12));
            g2d.setColor(Color.BLUE);

            FontMetrics fm = g2d.getFontMetrics();
            String text = "MOUSE BUTTON TESTER";

            int x = getWidth() - fm.stringWidth(text) - 10;
            int y = getHeight() - (fm.getAscent() - fm.getHeight()) - 10;

            g2d.drawString(text, x, y);
            g2d.dispose();
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

I suggest creating 2 classes.

1) Circle class
2) Square Class

Those classes will store info that you need, like X, y etc..

Initialize an array list that stores those objects & read from it in your paint method, proceed with painting them just like you do in your code.

(On a click event you simply create new object (circle/square) and add it into your array list)

RRIL97
  • 858
  • 4
  • 9
0

So here's how i understand how your code works so far: The user left clicks, those coordinates are recorded, and a square is rendered on the screen at those coordinates. When we click the coordinates are updated and on the next draw, the square is moved to a new position.

You were on the right track about needing a loop.

Here's the logic you need to implement:

Create an ArrayList as a member variable. The type can be a pair<int,int> object. So this arraylist will hold a list of X,Y coordinates. This arraylist will look something like this:

ArrayList<pair<int,int>> myRightClickCoords;

Once you make that list, every time the user clicks, record the click coordinates and insert them into the arraylist. That will look something like this:

myRightClickCoords.insert(new pair<int,int>(e.getX(),e.getY()));

Then, once that is added to your code, in your draw function, you can have a look that runs through the entire myRightClickCoords list and runs drawRect for each set of coordinates.

Once you get that working, you can do the same thing for left click and circles. Good luck!

Vpaladino
  • 320
  • 2
  • 12