Drawing a polygon based on clicks - java

I am trying to write a program that allows the user to draw a polygon by drawing a line every time they click within the frame. On the first click, a small square should be drawn. Every click following, a line should be drawn from where the endpoint of the last line is to where the user has clicked. Once the user clicks within the square that was made originally, the polygon will be completed and the square will disappear. My code is as follows; it runs but it does not operate correctly.
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.util.ArrayList;
import javax.swing.JFrame;
public class DrawPolygonComponent {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setSize(300, 400);
frame.setTitle("Draw a Polygon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final ArrayList<Point2D.Double> path = new ArrayList();
//addRectangle(frame, 10, 10);
//
class ClickListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent me) {
if (path.isEmpty()) {
System.out.println("First");
addRectangle(frame, me.getX(),me.getY());
path.add(new Point2D.Double(me.getX(),me.getY()));
} else {
System.out.println("Second");
Point2D.Double prev = path.get(path.size()-1);
addLine(frame, (int) prev.x, (int) prev.y,me.getX(),me.getY());
path.add(new Point2D.Double(me.getX(),me.getY()));
frame.repaint();
}
}
public void mousePressed(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
}
MouseListener listener = new ClickListener();
frame.addMouseListener (listener);
frame.setVisible (true);
}
public static void addRectangle(JFrame frame, int x , int y) {
RectangleComponent r = new RectangleComponent(x, y, 10, 10);
frame.add(r);
}
public static void addLine(JFrame frame, int x1, int y1, int x2, int y2) {
LineComponent line = new LineComponent(x1, y1, x2, y2);
frame.add(line);
}
}
/////////other
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
public class LineComponent extends JComponent {
private int px;
private int py;
private int x;
private int y;
public LineComponent(int px, int py, int x, int y){
this.px=px;
this.py=py;
this.x=x;
this.y=y;
}
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.drawLine(px,py,x,y);
}
}
////////other
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent {
private Rectangle box;
public RectangleComponent(int x,int y, int l, int w){
box = new Rectangle(x,y,l,w);
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.fill(box);
g2.draw(box);
}
}

You've attached your mouse listener to the frame, but not provided any means for the frame to paint your paths...
The component you have setup to "apparently" paint the polygon has not been added to the frame.
Instead.
Create a custom component, using something like JPanel. Attach the mouse listener to this component. Override it's paintComponent method. When a mouse event occurs (that should generate a new line), call repaint to request an update to the component.
Within the paintComponent method, re-draw all the lines.
Take a look at Java Applet Polygon array and How can I draw a polygon using path2d and see if a point is within it's area? and drawPolygon keeps drawing lines from starting (mousePressed) location to current (mouseDragged) location for some conceptional ideas
Ps You may also like to check out Performing Custom Painting

Related

Java Swing: Making a growing circle by mouse click on JPanel

I'm a beginner in Java and this time I'm trying to learn more by finding code examples and editing them, for example from this website. I have a JFrame and each time it (or more precise the JPanel in it) is clicked on, a circle is drawn which will grow/expand outwards like a water ripple. Each circle starts with a certain radius and will be removed or redrawn when reaching a bigger radius (I chose radius "r" from 10 to 200). I have two programs for this which almost work but are missing something. If I'm correct, I might also know what their problems are but I can't figure out how to solve them:
One generates growing circles but all of them have the same size, no matter when they're generated, since I can't find out how to assign the radius to a single circle. The code is adapted from here:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ripples extends JPanel implements ActionListener{
public int r = 10;
private ArrayList<Point> p;
public Ripples() {
p = new ArrayList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
p.add(new Point(e.getX(), e.getY()));
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.CYAN);
for (Point pt : p) {
g2.drawOval(pt.x-r, pt.y-r, 2*r, 2*r);
}
}
#Override
public void actionPerformed(ActionEvent evt) {
if(r<200){
r++;
} else {
r = 10;
}
repaint();
}
public static void Gui() {
JFrame f = new JFrame();
Ripples p = new Ripples();
p.setBackground(Color.WHITE);
f.setContentPane(p);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500,300);
f.setVisible(true);
Timer t = new Timer(20,p);
t.start();
}
public static void main(String[] args) {
Gui();
}
}
The other program(I've forgotten where I got it from) has circles with different radii depending on when they were generated, however the circles "flicker", because -as far as I understand- they are all processed at the same time, because the code doesn't include an Array to store and update each circle individually like the one above does:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Ripples extends JPanel {
int x,y;
int r = 10;
public Ripples(int x, int y) {
this.x = x;
this.y = y;
Timer t = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (r<200) {
r++;
} else {
r=10;
}
revalidate();
repaint();
}
});
t.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.CYAN);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawOval(x-r,y-r,2*r,2*r);
}
public static void Gui() {
JFrame f = new JFrame("Water Ripples");
JPanel p0 = new JPanel();
p0.setBackground(Color.WHITE);
f.add(p0);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBounds(100,100,600,500);
f.setVisible(true);
f.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Ripples rG = new Ripples(e.getX(), e.getY());
rG.setBackground(Color.WHITE);
f.add(rG);
}
});
}
public static void main(String[] args) {
Gui();
}
}
So how can I solve this so that I get the circles growing independent from each other? I'd prefer a solution/improvement/hint for the upper code because I think its structured better than the second one. Also, I apologize for not splitting the code into more classes and for possibly not sticking to naming conventions. I appreciate your help, thank you very much!
I added a Circle class to your Ripples code. This allows the ActionListener to treat each circle independently.
I started the GUI with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
Here's the code.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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;
import javax.swing.Timer;
public class Ripples extends JPanel implements ActionListener {
private List<Circle> circles;
public Ripples() {
circles = new ArrayList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent event) {
circles.add(new Circle(event.getPoint()));
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.CYAN);
g2.setStroke(new BasicStroke(3f));
for (Circle circle : circles) {
Point p = circle.getCenter();
int radius = circle.getRadius();
g2.drawOval(p.x - radius, p.y - radius,
2 * radius, 2 * radius);
}
}
#Override
public void actionPerformed(ActionEvent evt) {
for (Circle circle : circles) {
circle.incrementRadius();
}
repaint();
}
public static void createGUI() {
JFrame f = new JFrame("Ripples");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Ripples p = new Ripples();
p.setBackground(Color.WHITE);
p.setPreferredSize(new Dimension(500, 500));
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
Timer t = new Timer(20, p);
t.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createGUI();
}
});
}
public class Circle {
private int radius;
private final Point center;
public Circle(Point center) {
this.center = center;
this.radius = 10;
}
public void incrementRadius() {
radius += 1;
radius = (radius > 200) ? 10 : radius;
}
public int getRadius() {
return radius;
}
public Point getCenter() {
return center;
}
}
}
Edited to add:
I reworked the Ripples class code to separate the concerns. I created a DrawingPanel class to hold the drawing panel, a RipplesListener class to hold the MouseAdapter code, an Animation class to hold the Runnable that runs the animation of the circles, a RipplesModel class to hold the List of Circle instances, and finally, the Circle class.
I could have used a Swing Timer for the animation, but I'm more familiar with creating and running my own animation thread.
Yes, this code is more complicated than the original example. The coding style used here can be carried into larger, more complex Swing GUI development.
Here's the revised code. I hope it's a better example.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Ripples implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Ripples());
}
private Animation animation;
private DrawingPanel drawingPanel;
private RipplesModel model;
public Ripples() {
model = new RipplesModel();
}
#Override
public void run() {
JFrame frame = new JFrame("Ripples");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent event) {
stopAnimation();
frame.dispose();
System.exit(0);
}
});
drawingPanel = new DrawingPanel(model);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
animation = new Animation(this, model);
new Thread(animation).start();
}
public void repaint() {
drawingPanel.repaint();
}
private void stopAnimation() {
if (animation != null) {
animation.setRunning(false);
}
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private RipplesModel model;
public DrawingPanel(RipplesModel model) {
this.model = model;
setBackground(Color.WHITE);
setPreferredSize(new Dimension(500, 500));
addMouseListener(new RipplesListener(model));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(3f));
List<Circle> circles = model.getCircles();
for (Circle circle : circles) {
Point p = circle.getCenter();
int radius = circle.getRadius();
g2.setColor(circle.getColor());
g2.drawOval(p.x - radius, p.y - radius,
2 * radius, 2 * radius);
}
}
}
public class RipplesListener extends MouseAdapter {
private RipplesModel model;
public RipplesListener(RipplesModel model) {
this.model = model;
}
#Override
public void mousePressed(MouseEvent event) {
model.addCircle(new Circle(event.getPoint(),
createColor()));
}
private Color createColor() {
Random random = new Random();
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
return new Color(r, g, b);
}
}
public class Animation implements Runnable {
private volatile boolean running;
private Ripples frame;
private RipplesModel model;
public Animation(Ripples frame, RipplesModel model) {
this.frame = frame;
this.model = model;
this.running = true;
}
#Override
public void run() {
while (running) {
sleep(20L);
incrementRadius();
}
}
private void incrementRadius() {
List<Circle> circles = model.getCircles();
for (Circle circle : circles) {
circle.incrementRadius();
}
repaint();
}
private void sleep(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void repaint() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.repaint();
}
});
}
public synchronized void setRunning(boolean running) {
this.running = running;
}
}
public class RipplesModel {
private List<Circle> circles;
public RipplesModel() {
this.circles = new ArrayList<>();
}
public void addCircle(Circle circle) {
this.circles.add(circle);
}
public List<Circle> getCircles() {
return circles;
}
}
public class Circle {
private int radius;
private final Color color;
private final Point center;
public Circle(Point center, Color color) {
this.center = center;
this.color = color;
this.radius = 10;
}
public void incrementRadius() {
radius = (++radius > 200) ? 10 : radius;
}
public Color getColor() {
return color;
}
public int getRadius() {
return radius;
}
public Point getCenter() {
return center;
}
}
}
I'd prefer a solution/improvement/hint for the upper code
The second code is better because it uses:
a custom class to contain information about the object to be painted
an ArrayList to contain the objects to be painted
a Timer for the animation.
because I think its structured better than the second one.
Not a good reason. Use the code that provides the functionality that you require.
Restructure the code yourself. That is part of the learning experience.
Issues with the second code:
It doesn't compile. Why post code that doesn't compile? This implies you haven't even tested it.
the initial radius is assigned when the Position object is created.
When the Timer fires you need to iterate through the ArrayList to update the radius of each Position object.
The radius of the Position object is used in the painting code.
As an added change, maybe call the Position class Ripple. Then you can add another custom property for the Color of the ripple. Then when you add the Ripple to the ArrayList you randomly generate a Color. Then in the painting method you use the Color property of the Ripple class. This is how you make objects and painting more flexible and dynamic.

Keeping Shapes on Screen Help, can't figure out how to keep track of X,Y coordinates

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();
}
}
First, start by having a read through:
Performing Custom Painting
Painting in AWT and Swing
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:
How can I set in the midst?
Java JFrame .setSize(x, y) not working?
How to get the EXACT middle of a screen, even when re-sized
Graphics rendering in title bar
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();
}
}
}
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)
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!

MouseDragging still firing even after releasing

Hello and thanks in advance,
i am working with Graphics2D for a casino game (Roulette), so i am trying to add motion to the chips of the casino (The money), so for that i am using MouseDragged events and as a test i am working with only 1 ellipse.
code below
package roulette;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.Timer;
public class RouletteInterface extends JPanel{
private List<Shape> money = new ArrayList<>();
public RouletteInterface() {
createEllipseGrap();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g4d = (Graphics2D) g.create();
paintEllipseGrap(g4d, g);
g4d.dispose();
}
protected void createEllipseGrap() {
Ellipse2D elipse = new Ellipse2D.Double(100, 100, 30, 30);
money.add(elipse);
addMouseListener(new moneyMouseListener());
addMouseMotionListener(new moneyMouseListener());
}
protected void paintEllipseGrap(Graphics2D g3d, Graphics g) {
g3d.setColor(Color.BLUE);
g3d.fill(money.get(0));
}
private class moneyMouseListener extends MouseAdapter {
int dragging;
private int x;
private int y;
#Override
public void mousePressed(MouseEvent e) {
if(money.get(0).contains(e.getPoint())) {
x = e.getX();
y = e.getY();
dragging = 0;
} else {
return ;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if(dragging == 0) {
x = e.getX();
y = e.getY();
Ellipse2D elipse = new Ellipse2D.Double(x, y, 30, 30);
money.set(0, elipse);
repaint();
} else {
}
}
#Override
public void mouseReleased(MouseEvent m) {
dragging = 1;
repaint();
}
}
}
public class principal{
public static void main(String[] args) {
new principal();
}
public principal() {
JFrame frame = new JFrame();
frame.add(new RouletteInterface());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
What's the problem?
The MouseDragged event is still firing even after i release the mouseclick so the circle is still moving with my cursor when i click and drag on another side of the window
Your problem is that you are adding two different instances of your moneyMouseListeners as MouseListener and as MouseMotionListener:
addMouseListener(new moneyMouseListener());
addMouseMotionListener(new moneyMouseListener());
You would have to do it like that:
moneyMouseListener mListener = new moneyMouseListener();
addMouseListener(mListener);
addMouseMotionListener(mListener);
PS.: When using a variable like your "dragging" variable that is only used to assign a "1" or a "0" you should use a boolean variable with "true" and "false" ;)
Also, you might want to consider drawing/undrawing the chip using XOR mode of the Graphics, rather than calling repaint() all the time.
Press: undraw the chip in normal mode, then xor draw it.
Drag: XOR draw the chip, reset the position, XOR draw again.
Release: XOR draw the chip, then draw in normal mode.
That way if you move the chip over something in the background (or over another chip) you don't damage the other chip or the background.

Paint something in JFrame after an event occurred?

How can I paint something in a frame in an event handler in java? Because I want to write the game Breakout and there I would need to repaint the entire screen in the event handler.
public void mouseMoved(MouseEvent e, Graphics g)
{
// if mouse was moved then rearrange paddle
double x = e.getX() - paddle_width;
double y = e.getY() - paddle_height;
this.repaint();
g.setColor(Color.BLACK);
g.fillRect(x, y, paddle_width, paddle_height);
}
You can create your drawing panel extending JPanel and override the paintComponent.
Then you can have a model (By model i mean the data about what you want to paint)
Then you can add MouseMotionListener which would manipulate your model.
Notify the model changes to the drawing panel so that it will update the painting based on the model changes.
The below code should help you progress.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Demo extends JFrame {
public static void main(String[] args) {
Demo frame = new Demo();
frame.setVisible(true);
}
public Demo() throws HeadlessException {
super();
init();
}
private void init() {
Point start = new Point(0, 0);
Paddle paddle = new Paddle(start, 20, 20);
DrawingPanel drawingPanel = new DrawingPanel(paddle);
setContentPane(drawingPanel);
pack();
}
class DrawingPanel extends JPanel implements MouseMotionListener {
private Paddle paddle;
public DrawingPanel(Paddle paddle) {
super();
this.paddle = paddle;
this.addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(paddle.point.x, paddle.point.y, paddle.width, paddle.height);
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
paddle.point = new Point(e.getX(), e.getY());
repaint();
}
}
class Paddle {
Point point;
Integer height, width;
public Paddle(Point point, Integer height, Integer width) {
super();
this.point = point;
this.height = height;
this.width = width;
}
}
}

Java MouseListener Not Working

I am trying to get the console to print when the mouse is pressed within an object of class RenderCanvas which extends JPanel. However, I am getting no feedback when I press the mouse down in the window. Any suggestions as to what I might be able to change to make the MouseListener work?
Here is my code:
RenderCanvas Class:
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
public class RenderCanvas extends JPanel {
private List<Rect> rectangles = new ArrayList<Rect>();
private List<Line> lines = new ArrayList<Line>();
public void renderCanvas() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
addRect(0, 0, 200, 200, Color.ORANGE);
System.out.println(e);
}
});
}
public void paintComponent(Graphics g) {
for (Rect rectangle : rectangles) {
rectangle.draw(g);
}
for (Line line : lines) {
line.draw(g);
}
}
public void addRect(int x, int y, int width, int height, Color color) {
Rect rectangle = new Rect(x, y, width, height, color);
this.rectangles.add(rectangle);
}
public void addLine(int y, int width, Color color) {
Line line = new Line(y, width, color);
this.lines.add(line);
}
}
Main Class:
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Main {
public static void main(String[] args) {
JFrame window = new JFrame("Window");
RenderCanvas canvas = new RenderCanvas();
window.setContentPane(canvas);
window.setSize(640, 360);
window.setLocation(640, 360);
window.setVisible(true);
}
}
Thanks in advance for any help!
public void renderCanvas() is NOT a constructor. Change
public void renderCanvas()
to
public RenderCanvas()
Notice the upper-case "R" and the absence of the "void" return type
void RenderCanvas() is not being called. I believe you mean just public RenderCanvas() instead of public void RenderCanvas, since you're only using the ctor in the main method.
I think you're intending this method:
public void renderCanvas() {
to be a constructor for the RenderCanvas class; it's not, though, for two reasons: it's not capitalized the same way (small r vs capital R) and also it has a return type. Constructors have no return type; the line should look like
public RenderCanvas() {
Because this isn't a constructor, it's a method, and nobody's calling it, so your event handler is never being added.

Categories

Resources