Hey guys I need help I am trying to make a program where I can draw in a window with the mouse. So far I have it to where when I click a dot appears but I need to add a drag method so that when I drag the mouse across the page it draws stuff. Can someone look at my code and help me out where you can?
Here is my code:
import javax.swing.*;
import java.awt.event.*;
public class mouse {
private static int x,y;
private static draw object = new draw ();
public static void main(String[] args){
JFrame frame = new JFrame ("Mouse");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.add(object);
object.addMouseListener(new AL());
}
static class AL extends MouseAdapter{
public void mousePressed(MouseEvent e){
x = e.getX();
y = e.getY();
object.drawing(x, y);
}
public void mouseDragged( MouseEvent e) {
x= e.getX();
y= e.getY();
object.drawing(x, y);
}
}
}
and
import javax.swing.*;
import java.awt.*;
public class draw extends JPanel {
private static int x,y;
public void drawing (int xx, int yy){
x=xx;
y=yy;
repaint();
}
public void paintComponent (Graphics g){
g.setColor(Color.black);
g.fillOval(x, y, 10, 10);
}
}
One idea that I have is to add your mouse coordinates each to a separate list whenever the mouse is clicked and draw based on the size of the lists, however since you are using mouse dragged you could just use Path2D.lineTo(x, y) and use e.getX() and e.getY() for the x and y coords. After this use Path2D.moveTo(x, y) to make sure line path is appended for each pixel the mouse moves (this makes sure that each movement doesn't look like a straight line, but rather like a line moving whatever direction you're "drawing" in). Also, a few tips:
The void mouseDragged usually works better when used in mouseMotionAdapter because from my experience it usually doesn't register the event in just mouseAdapter.
Since this is a drawing program, personally I'd set a variable for the size of your circle to be used in the future if you actually are planning to expand this into something bigger (example: g.fillOval(x, y, brushSize, brushSize)).
Related
I have a school assignment to make a program which creates a small window, and when you move the mouse around without clicking it displays the coordinates above in BLACK text, and when you hold and drag the mouse it displays the coordinates above in RED text. I have the program working so it displays the coordinates above the mouse for both events but I'm not sure how to change the color to red when the mouse is being held down. Here is what I have so far:
class MyFrame extends Frame{
int x;
int y;
public void paint(Graphics g){
g.drawString(
"" + x + ", " + y, x, y);
}
}
class MyMouseListener extends MouseMotionAdapter{
MyFrame ref;
MyMouseListener(MyFrame mFrame){
ref = mFrame;
}
public void mouseDragged(MouseEvent e){
ref.x = e.getX();
ref.y = e.getY();
ref.repaint();
}
public void mouseMoved(MouseEvent e){
ref.x = e.getX();
ref.y = e.getY();
ref.repaint();
}
}
Does this need to somehow be done in the mouseDragged() method or in the MyFrame class? Is there any way to make an if statement for which method is being called so I could set a color for if(mouseDragged()) or something like that?
On your paint method call g.setColor(color).
Set the color in mouse events to black and red accordingly.
I'm trying to make Pong with Java and Swing. However, I have two problems - one, the rectangle on-screen doesn't move at all, and two, a NullPointerException is happening even though the code still runs. Here are my two files:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Pong extends JFrame implements KeyListener {
private static final long serialVersionUID = -5782301423436L;
JPanel panel;
Paddle paddle1;
public Pong() {
super("Pong");
panel = new JPanel();
this.add(panel);
super.setPreferredSize(new Dimension(800, 600));
super.setVisible(true);
super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
super.pack();
addKeyListener(this);
paddle1 = new Paddle(100, 300);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Pong game = new Pong();
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.BLACK);
this.paddle1.draw(g);
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
// I've tested this part and the w and s key presses
// are still detected, but nothing happens. Why not?
public void keyPressed(KeyEvent keyEvent) {
int key = keyEvent.getKeyCode();
if (key == KeyEvent.VK_ESCAPE) {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
} else if (key == KeyEvent.VK_W) {
this.paddle1.up();
} else if (key == KeyEvent.VK_S) {
this.paddle1.down();
}
}
}
import java.awt.Graphics;
public class Paddle {
// Position of the paddle's center
int x;
int y;
public Paddle(int x, int y) {
this.x = x;
this.y = y;
}
public void draw(Graphics g) {
g.fillRect(this.x - 10, this.y - 40, 20, 80);
}
// Up is negative because Java coordinates
public void up() {
this.y -= 30;
}
public void down() {
this.y += 30;
}
}
I've tested the keyPressed method in the Pong file, and when the w and s keys are pressed, it does, in fact, detect them (it will print a line out to the console). I'm very new to graphics in Java, and this is the first thing I've tried creating that's not copy-pasted from a tutorial on YouTube. I've been looking at my code for about an hour and can't find where the error could possibly be. Any and all help would be greatly appreciated.
I've checked the code and can help you solve the errors.
First, here you've shown the Paddle using paint() method of the JFrame Pong. You're detecting the 'W' and 'S' keys and according to the key you've written the code to update the y co-ordinate in the Paddle class.
But, the problem here is, you're just updating the y co-ordinate. You're not drawing the paddle with new co-ordinates again. So, after setting the new y value, you should draw the paddle again.
So, in the keyPressed() method, after
this.paddle1.up();
and
this.paddle1.down();
you should again call the draw() method of the Paddle class that will draw the Paddle at the modified location.
In this draw() method you're passing a Graphics object which is the graphics configuration of the current JFrame Pong. So, this can be get using getGraphics() method of the JFrame.
So, the line to add after up() or down() will be
this.paddle1.draw(getGraphics());
Since we are dealing with graphics, it is also the proper thing to repaint the JFrame once you change something in its graphics. If you have added only the above line after up() and down() method in the keyPressed() method, you will see the Paddle is not moving. Its previous drawing will be as it is and as per the key pressed, new Paddle will be drawn upwards or downwards. So, instead of a moving paddle you will see a vertical bar. This is happening because we are modifying the graphics but not painting the JFrame again. So, it will just add the new rectangle in the JFrame keeping previous as it is.
So, to get rid of this, you should use repaint() method of the JFrame so that it draws only the latest screen.
So, the complete keyPressed() method would be like :
#Override
public void keyPressed(KeyEvent keyEvent) {
int key = keyEvent.getKeyCode();
if (key == KeyEvent.VK_ESCAPE) {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
} else if (key == KeyEvent.VK_W) {
this.paddle1.up();
this.paddle1.draw(getGraphics());
repaint();
} else if (key == KeyEvent.VK_S) {
this.paddle1.down();
this.paddle1.draw(getGraphics());
repaint();
}
}
So, now after detecting correct keys, it is drawing the paddle again and
after that discards the previous ones as well so that while you will run this code, you will be able to see the paddle is moving as per the key pressed.
Now, about the NullPointerException. I tried to run this code but I could not reproduce such exception. So, after trying the suggested code, if you encounter NPE, you can update the stack trace to get it solved.
I have read the comments and they are very useful. Do check the link that explains better way for listening to the key events.
Thank you.
What I'm trying to do is to draw circles and lines.
When the mouse is first pressed, I draw a small circle. Then, I need
to draw a line connecting the original point to the current
position of the mouse. When the mouse is released, the line
remains, but when I click again, everything disappears and I draw a
circle and a line all over again.
This is the code I have so far:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Canvas4 extends JComponent implements MouseListener, MouseMotionListener {
//constructor
public Canvas4() {
super();
addMouseListener(this);
addMouseMotionListener(this);
}
//some variables I may or may not use
int pressedX;
int pressedY;
int currentX;
int currentY;
int startDragX;
int startDragY;
int endDragX;
int endDragY;
int mouseReleasedX;
int mouseReleasedY;
//mouse events
public void mouseClicked(MouseEvent event) { }
public void mouseEntered(MouseEvent event) { }
public void mouseExited(MouseEvent event) { }
public void mousePressed(MouseEvent event) {
pressedX = event.getX();
pressedY = event.getY();
drawCircle();
startDragX = pressedX;
startDragY = pressedY;
}
public void mouseReleased(MouseEvent event) {
mouseReleasedX = event.getX();
mouseReleasedY = event.getY();
//repaint() here maybe???
}
//mouse motion events
public void mouseDragged(MouseEvent event) {
System.out.println("You dragged the mouse.");
endDragX = event.getX();
endDragY = event.getY();
drawLine();
}
public void mouseMoved(MouseEvent event) { }
//draw circle when mouse pressed
//this method works fine
public void drawCircle() {
Graphics g1 = this.getGraphics();
g1.setColor(Color.CYAN);
g1.fillOval(pressedX, pressedY, 10, 10);
}
//draw line when mouse dragged
//this is where I need help
public void drawLine() {
Graphics g2 = this.getGraphics();
g2.setColor(Color.RED);
g2.drawLine(pressedX, pressedY, mouseReleasedX, mouseReleasedY);
}
}
Then of course, there's a main method that creates the class object and adds it to a frame and whatnot.
My two specific questions are:
how do I draw a line as it's dragged? The code I have currently only draws a line to the last point of mouse release.
When do I repaint? If I repaint in the drawCircle() method, the circle blinks in and out instead of disappearing on the next click.
If you want to draw circles and lines then you need to keep an ArrayList of Shapes to draw. You would add an Ellipse2D.Double for the circle and a Line2D.Double for the line.
In the mousePressed event you add the Ellipse2D.Double object to the ArrayList, then you set up a temporary Line2D.Double object to contain your line information.
In the mouseDragged event you update Line2D.Double object with the new end point and then invoke repaint().
In the mouseReleased event you add the Line2D.Double object to the ArrayList and clear the variable referencing the Line2D.Double object.
Then in the paintComponent() method you add logic to:
iterate through the ArrayList to paint each Shape.
draw the Line2D.Double object when not null
Check out the Draw On Component example found in Custom Painting Approaches. This will show you the basic concept of this approach.
In the example the ArrayList only contains information on Rectangles so you will need to make it more generic to hold a Shape object. Both Ellispse2D.Double and Line2D.Double implement the Shape interface.
For drawing lines i have this.When you click mouse left you retain a point next click will retain another point making a line between them , and with mouse right you make the line between first point and last point (you can delete this "if (isClosed)" if you dont want)
Another thing : it's not a good precision because pointlocation return a double and drawline need an integer and the cast loses precision.
public class PolygonOnClick extends JPanel implements MouseListener, MouseMotionListener {
ArrayList<Point> points = new ArrayList<>();
static boolean isClosed = false;
PolygonOnClick() {
JFrame frame = new JFrame("Polygon ON CLICK");
frame.addMouseListener(this);
frame.setLocation(80, 50);
frame.setSize(1000, 700);
frame.add(this);
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
graphics.drawString("Click stanga pentru a incepe a desena , click dreapta pentru a inchide poligonul ", 15, 15);
for (int i = 1; i < points.size(); i++) {
graphics.drawLine((int) points.get(i - 1).getX(), (int) points.get(i - 1).getY(), (int) points.get(i).getX(), (int) points.get(i).getY());
}
if (isClosed) {
graphics.drawLine((int) points.get(points.size() - 1).getX(), (int) points.get(points.size() - 1).getY(), (int) points.get(0).getX(), (int) points.get(0).getY());
}
}
#Override
public void mousePressed(MouseEvent e) {
if (!isClosed) {
if (e.getButton() == MouseEvent.BUTTON1) {
points.add(e.getPoint().getLocation());
}
}
if (e.getButton() == MouseEvent.BUTTON3) {
isClosed = true;
}
repaint();
}
I created this java program and I wanted an output of which if int x and int y are above 100, it would draw a rectangle. But it doesn't. How can I make it work?Is there another line of code I need to add?
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener{
public static JFrame njf = new JFrame("Test");
public static int x, y;
public static void main(String[] args){
GameSetup gs = new GameSetup();
njf.add(gs);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
njf.addMouseListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
});
if(x > 100 && y > 100){
g.drawRect(10, 10, 100, 100);
}
}
public GameSetup(){
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
njf.setVisible(true);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Okay, there are several things wrong with the code that you included above.
The first that stood out to me was the way that you are adding the mouse action listener to frame. There are multiple things that are wrong with this.
First of all, you are doing this in the paintComponent method, which, if it works, is still considered to be bad practice because the paintComponent method may be called multiple times. Do that, as pointed out by the comments, in the constructor of the panel.
The second is that you are adding the mouse listener to the frame, not the panel, which doesn't work because the panel is "above" the frame, so the mouse event will only be recognized within the panel. Your best bet here is to add a MouseMotionListener directly to the panel itself.
The third is that you are implementing the MouseMotionListenerinterface in the GameSetup class, but never actually doing anything with this implementation. So what I did was that I got rid of the inner class, and just had the panel be its own MouseMotionListnener
The second thing that is wrong with the code is that the paintComponent method is only called at certain points in time (see this). That means that even though the mouse might have moved within the zone, your paintComponent method isn't being called to update the screen accordingly. For this, you need to call the repaint method for your panel.
The third is that you didn't set a size for your panel, and the default one is 0x0, so you need to set a size of your panel (which should be the same as the frame itself) (if you want to keep the default layout).
All of that being said, here is your code that I fixed up. I added a variable called enteredZone to keep track of if the mouse had previously entered the zone, so that the rectangle would stay up even if the mouse left the zone after entering it (its your choice if you want to keep it). Note that there are other things with this code that might be considered bad practice, but this is enough to get you started:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {
public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean enteredZone = false;
public static void main(String[] args) {
GameSetup gs = new GameSetup();
gs.addMouseMotionListener(gs);
njf.add(gs);
njf.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.fillRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 100 && y > 100 || enteredZone){
g.drawRect(10, 10, 100, 100);
enteredZone = true;
}
}
public GameSetup() {
super();
setSize(500, 500);
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
if (x > 100 && y > 100) repaint();
}
}
I am having a problem with the following code. My intent is to store the coordinates of a mouse click into an arraylist using getPoint, and then draw a rectangle at each location that the user has clicked. I have searched high and low for how to extract the x and y coordinates individually from a getPoint object to no avail. I am new to java, the line that is giving me trouble at compile time is:
g2.drawRect(coordinateList(j).getHeight(),coordinateList(j.getWidth(),3,3);
I know that I am probably way off, but how can I extract the x and y coordinates of a point individually from an array list, one item of the array by one in order to repaint a rectangle at the new click point and also all the previous clicks as well?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.event.MouseListener;
import java.awt.Point;
import java.util.*;
public class ClickCloud extends JPanel
{
private int pointxy;
//private Rectangle2D.Double r1;
private boolean mouseClick;
private int count;
//private Point[] points;
private Point coordinates = new Point(0, 0);
private ArrayList<Point> coordinateList = new ArrayList<Point>();
public ClickCloud() {
this.setPreferredSize(new Dimension(500,500));
this.addMouseListener(new MyMouseListener());
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (int j = 0; j < count; j++) {
g2.setStroke(new BasicStroke(1.0f));
g2.setPaint(Color.BLUE);
g2.drawRect(coordinateList(j).getHeight(),coordinateList(j.getWidth(),3,3);
}
}
private class MyMouseListener implements MouseListener {
public void mouseClicked(MouseEvent me) {
count++;
coordinates.setLocation(me.getPoint());
coordinateList.add(coordinates.getLocation());
repaint();
}
public void mousePressed(MouseEvent me) { }
public void mouseReleased(MouseEvent me) { }
public void mouseEntered(MouseEvent me) { }
public void mouseExited(MouseEvent me) { }
}
public static void main(String[] args) {
JFrame f = new JFrame("ClickCloud demo");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new FlowLayout());
f.add(new ClickCloud());
f.pack();
f.setVisible(true);
}
}
Thanks,
T
Forget all the getLocation and setLocation. It's redundant. Just store me.getPoint() in your coordinateList.
Then you can get the x and y coordinates with point.getX() and point.getY() respectively.
In paintComponent, there is an easier way to iterate over a list of points:
for (Point coordinate : coordinateList) { //"for each coordinate in coordinateList"
//do something with coordinate.getX() and coordinate.getY()
}
You are not getting properly the points from the ArrayList.
g2.drawRect(coordinateList(j).getHeight(),coordinateList(j.getWidth(),3,3);
To get the item at index j with an ArrayList, you simply use the method get():
Point point = coordinateList.get(j);
Then the problem is that pointonly represents, well, points... They only have X and Y coordinates, not width and height. If I try to guess what you want to do and assume that you want to draw 3x3 rectangles where the user has clicked, you would call drawRect() like this:
g2.drawRect(point.getX(), point.getY(), 3, 3);
Also:
You don't need to handle a count variable to know the number of points you have in your ArrayList. Just use the size() method of coordinateList or even better, use an enhanced for loop.
You can use MouseAdapter instead of MouseListener to only override the events you need.
You don't need the coordinates member and the get/setLocation stuff. Just write coordinateList.add(me.getPoint());