Creating "paint" application in Java - java

I have an array list that keeps track of the "dots" and am using an array to keep track of the different sizes. The size is changed via a mouseWheelListener and the change is saved in that array. However for some reason ALL of the dots are resized which is not what I want. After running through it a few times everything looks like it should work but I must be missing something simple. My code as follows.
//********************************************************************
// DotsPanel.java
// Represents the primary panel for the Dots program.
//********************************************************************
import java.util.ArrayList;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class DotsPanel extends JPanel
{
private int SIZE = 10; // radius of each dot
private int[] dotSizes = new int[10000];
int i = 0;
private ArrayList<Point> pointList;
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
{
pointList = new ArrayList<Point>();
addMouseListener (new DotsListener());
addMouseMotionListener(new DotsListener());
addMouseWheelListener(new DotsListener());
setBackground(Color.red);
setPreferredSize(new Dimension(300, 200));
}
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.setColor(Color.cyan);
for (Point spot : pointList)
//change size to sizes[n]
page.fillOval(spot.x-dotSizes[pointList.size()-1], spot.y-dotSizes[pointList.size()-1], dotSizes[pointList.size()-1]*2, dotSizes[pointList.size()-1]*2);
page.drawString("Count: " + pointList.size(), 5, 15);
}
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener, MouseWheelListener
{
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event) {}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
#Override
public void mouseDragged(MouseEvent event)
{
pointList.add(event.getPoint());
dotSizes[pointList.size()-1] = SIZE;
//store size of dot here
repaint();
}
#Override
public void mouseMoved(MouseEvent event) {}
#Override
public void mouseWheelMoved(MouseWheelEvent event)
{
SIZE -= event.getWheelRotation();
repaint();
}
}
}

In this code:
for (Point spot : pointList)
//change size to sizes[n]
page.fillOval(spot.x-dotSizes[pointList.size()-1], spot.y-dotSizes[pointList.size()-1], dotSizes[pointList.size()-1]*2, dotSizes[pointList.size()-1]*2);
you are using a single dot size for all the dots: the size of the last dot that was added. (There's even a comment there to fix the problem!) You need to iterate with an index so you can index into the dotSizes array as well as the pointList ArrayList:
for (int i = 0; i < pointList.size(); ++i) {
Point spot = pointList.get(i);
int size = dotSizes[i];
page.fillOval(spot.x-size, spot.y-size, size*2, size*2);
}
It would be much better to define your own "point with size" class that encapsulates a Point and a size:
class Spot extends Point {
public int size;
public Spot(int x, int y, int size) {
super(x, y);
this.size = size;
}
}
Then change your pointList to an ArrayList<Spot> and you can go back to iterating over a single list:
for (Spot spot : pointList)
page.fillOval(spot.x-spot.size, spot.y-spot.size, 2*dot.size, 2*dot.size);
Of course, you'll also have to update the code that adds points to the list accordingly.
As an aside, it seems to me that your mousePressed handler has a bug: it does not add a size when it adds a point. Switching to a Spot class would also help avoid that kind of problem.

for (Point spot : pointList)
//change size to sizes[n]
page.fillOval(spot.x-dotSizes[pointList.size()-1], spot.y-dotSizes[pointList.size()-1], dotSizes[pointList.size()-1]*2, dotSizes[pointList.size()-1]*2);
Here is your problem. You aren't changing the size to size[n] but you are changing the size of every one to size[pointList.size()-1] or in other words, the last one. You will probably have to use a regular for loop unless you want to find the index of the current point.

Related

how to make custom sized components in swing

I have 2 Components (which are both derived from jComponent). One is a Map and the other one are Territories within this map as you can see at the picture below.
The Map is drawn on a fixed size of 1200x800 so far. And for each territorys I have a list of points, which will connected be a the shapes of each country.
Drawing everything working quite good so far. But when I click on a country always the last drawn territory gets called. It seems like every territory is an layer over the whole map. How can I make it work, that if I click on a single territory that only this gets clicked. So that if I click on China, the click event of china gets called?
Below is the Code of the 2 Components in case it helps:
Map.java
public class Map extends JComponent {
private Collection<Territory> territories;
public Map(Collection<Territory> territories) {
super();
this.territories = territories;
}
#Override
public void paintComponent(Graphics graphics)
{
graphics.setColor(new Color(8, 114, 200));
graphics.fillRect(0, 0, this.getWidth(), this.getHeight());
for (Territory tmp : this.territories) {
TerritoryComponent territoryComponent = new TerritoryComponent(tmp);
this.add(territoryComponent);
}
this.updateUI();
}
}
TerritoryComponent.java
public class TerritoryComponent extends JComponent implements MouseListener {
private Territory territory;
public TerritoryComponent(Territory tmp) {
super();
this.setSize(this.getMaximumSize());
this.addMouseListener(this);
this.territory = tmp;
}
#Override
public void paintComponent(Graphics graphics)
{
for (Patch patch : this.territory.getPatches()) {
ArrayList<Point> points = patch.getPoints();
int x[] = new int[points.size() + 1];
int y[] = new int[points.size() + 1];
for (int i = 0; i < points.size(); i++) {
x[i] = (int) points.get(i).getX();
y[i] = (int) points.get(i).getY();
}
x[points.size()] = (int) points.get(0).getX();
y[points.size()] = (int) points.get(0).getY();
graphics.setColor(new Color(255, 255, 255));
graphics.fillPolygon(x, y, points.size() + 1);
graphics.setColor(new Color(52, 52, 52));
graphics.drawPolyline(x, y, points.size() + 1);
}
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("clicked " + this.territory.getName());
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
And for each territorys I have a list of points,
Create a Polygon Object to represent each of your territories.
Add each Polygon to an ArrayList
In the paintComponent() method you just iterate through the ArrayList to paint each Polygon
if I click on a single territory that only this gets clicked.
In the mouseClicked(...) event you then get the mouse point and your iterate through the ArrayList containing all your Polygons. You can then use the Polygon.contains(...) method to determine which territory you clicked on.
Also don't use the updateUI() method. The method should only be invoked when the LAF is changed. It should especially not be invoked in a painting method as this will cause the component to potentially repaint itself.

Having trouble creating a dot drawing program and casting

Trying to do a mouse event assignment. The idea is that when the user clicks the mouse the program draws a small green dot, when the mouse is released it should create a small orange dot 5 pixels down and 5 pixels right of it. The assigment requires the three programs, Dots, DotsPanel, and DrawDots. The program should also have a counter of total dots. Right now the programs compile, but the program completely breaks and gives me tons of errors when I try to run it. I'm a bit lost right now as I'm new to this GUI and user mouseEvents. Thank you! I specifically have trouble of how to get past the casting the Dots class as a Point.
Here is a copy of the instructions:
Modify the “Dots” example. Include a Dots class that contains a constructor to initialize the color and point location of the dot. The Dots class should also include two accessor methods. The ArrayList will now contain a list of the dots to draw instead of points. When the mouse is pressed, the program draws a green circle (as in the original design). When the mouse is released, the program draws a yellow circle translated 5 pixels right and 5 pixels down from the released location. Be sure to keep track of the total number of dots. You should have three files: Dots, DotsPanel, DrawDots. (10 points)
/**
* #(#)Dots.java
*
*
* #author
* #version 1.00 2015/5/16
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Dots
{
Point p;
Color col;
public Dots(Color c, Point x)
{
p=x;
col=c;
}
public Point getPointP()
{
return p.getLocation();
}
public Color getPointC()
{
return col;
}
}
....
//represents the primary panel for the Dots program on which the
//dots are drawn
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class DotsPanel extends JPanel
{
private final int WIDTH = 300, HEIGHT = 300;
private final int RADIUS = 6;
private ArrayList<Dots> pointList;
private int count;
//Sets up this panel to listen for mouse events.
public DotsPanel()
{
pointList = new ArrayList<Dots>();
count = 0;
addMouseListener(new DotsListener());
setBackground(Color.black);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
}
//Draws all of the dots stored in the list
public void paintComponent(Graphics page)
{
super.paintComponent(page);
//Retrieve an iterator for the ArrayList of points
Iterator pointIterator = pointList.iterator();
while(pointIterator.hasNext())
{
page.setColor(Color.green);
Point drawPoint = (Point) pointIterator.next();
page.fillOval(drawPoint.x - RADIUS, drawPoint.y - RADIUS,
RADIUS * 2, RADIUS * 2);
page.setColor(Color.yellow);
Point drawPoint2 = (Point) pointIterator.next();
page.fillOval(drawPoint2.x - RADIUS+5, drawPoint2.y - RADIUS+5,
RADIUS * 2, RADIUS * 2);
}
page.drawString("Count: " + count, 5, 15);
}
//represents the lister for mouse events
private class DotsListener implements MouseListener
{
//Adds the current point to the list of points and redraws
//whenever the mouse button is pressed
public void mousePressed(MouseEvent event)
{
Dots dot1 = new Dots(Color.GREEN, event.getPoint());
pointList.add(dot1);
count++;
repaint();
}
public void mouseReleased(MouseEvent event)
{
Dots dot2 = new Dots(Color.YELLOW, event.getPoint());
pointList.add(dot2);
count++;
repaint();
}
//Provide empty definitions for unused event methods
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
}
}
.....
//demonstrates mouse events and drawing on a panel
import javax.swing.*;
public class DrawDots
{
//Creates and displays the application frame
public static void main(String[] args)
{
JFrame dotsFrame = new JFrame("Dots");
dotsFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dotsFrame.getContentPane().add(new DotsPanel());
dotsFrame.pack();
dotsFrame.setVisible(true);
}
}
First you should use Iterator<Dots> pointIterator = pointList.iterator();. This helps the compiler to warn you in case of uncastable types (this is the first error you got). In your paintComponent method you should use Point drawPoint = pointIterator.next().getPointP(); and Point drawPoint2 = pointIterator.next().getPointP(); a view lines later.After that modifications the program runs (at least on my machine).

How to find and write the final coordinates(x,y) of the all the components created in to a text file by clicking a write button

This program is about creating components and moving them randomly in JApplet and removing the components if required. Every mouse click creates a new component. After creating component we can click on it and drag it where ever we want. Double clicking on the component removes it. I was successful in creating, moving and removing components.
For example i created three components on the JApplet by clicking three times randomly at different places on the JApplet.Please click here to view created components I moved them randomly around the screen. Please click here to view JApplet after randomly moving them around screen My goal is to write the final coordinates(x,y) of their position on the screen for all components created in to a text file by clicking a write button. I have no idea about mouseReleased method. Please help me with this. Thank you. Your help is very much appreciated.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.geom.*;
import javax.swing.*;
This is my main class
public class MouseTest extends JApplet
{
public void init()
{
EventQueue.invokeLater(new Runnable() {
public void run()
{
MousePanel panel = new MousePanel();
add(panel);
}
});
}
public static void main(String[] args)
{
EventQueue.invokeLater(new mainThread());
}
}
class mainThread implements Runnable
{
public void run()
{
JPanel panel = new MousePanel();
JFrame frame = new JFrame("MouseTest");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,200);
frame.setVisible(true);
}
}
class MousePanel extends JPanel
{
public MousePanel()
{
squares = new ArrayList<Rectangle2D>();
current = null;
addMouseListener(new MouseHandler());
addMouseMotionListener(new MouseMotionHandler());
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// draw all squares
for (Rectangle2D r : squares)
g2.draw(r);
}
/**
* Finds the first square containing a point.
* #param p a point
* #return the first square that contains p
*/
public Rectangle2D find(Point2D p)
{
for (Rectangle2D r : squares)
{
if (r.contains(p)) return r;
}
return null;
}
/**
* Adds a square to the collection.
* #param p the center of the square
*/
public void add(Point2D p)
{
double x = p.getX();
double y = p.getY();
current = new Rectangle2D.Double(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH,
SIDELENGTH);
squares.add(current);
repaint();
}
/**
* Removes a square from the collection.
* #param s the square to remove
*/
public void remove(Rectangle2D s)
{
if (s == null) return;
if (s == current) current = null;
squares.remove(s);
repaint();
}
private static final int SIDELENGTH = 10;
private ArrayList<Rectangle2D> squares;
private Rectangle2D current;
// the square containing the mouse cursor
these are methods for defining and dragging and removing the object
private class MouseHandler extends MouseAdapter
{
public void mousePressed(MouseEvent event)
{
// add a new square if the cursor isn't inside a square
current = find(event.getPoint());
if (current == null) add(event.getPoint());
}
public void mouseClicked(MouseEvent event)
{
// remove the current square if double clicked
current = find(event.getPoint());
if (current != null && event.getClickCount() >= 2) remove(current);
}
}
private class MouseMotionHandler implements MouseMotionListener
{
public void mouseMoved(MouseEvent event)
{
// set the mouse cursor to cross hairs if it is inside
// a rectangle
if (find(event.getPoint()) == null) setCursor(Cursor.getDefaultCursor());
else setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
public void mouseDragged(MouseEvent event)
{
if (current != null)
{
int x = event.getX();
int y = event.getY();
// drag the current rectangle to center it at (x, y)
current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH);
repaint();
}
}
}
}
Why do you keep changing the requirement???? See original question: How to find final coordinates(x & y) of the objects position in JApplet and write them to a text file
First you wanted to write out the location of the moved component after the drag was finished.
Then you wanted to write out the location of "all" components after the drag was finished.
Now you want to write out the location of all the components after a "button" is clicked.
I have no idea about mouseReleased method.
What does this have to do with anything? That was the suggestion for your requirement in your last question. Since your requirement has changed it is no longer needed.
My goal is to write the final coordinates(x,y) of their position on the screen for all components created in to a text file by clicking a write button.
Then you need to add an ActionListener to the button. You have already been given a link to the Swing tutorial on How to Write an ActionListener so I guess the question is what code should be included in the ActionListener?
In you last question you stated:
I know how to get the location of a component
I know how to write data to a file
So the only remaining problem is how to get all the components on the panel? To do this you can use the Container.getComponents() method on your panel containing all the dragged components. The basic code for your ActionListener would be something like:
for (Component component: panel.getComponents())
{
Point location = component.getLocation();
// write the location to the file
}
I'll let you add the code for opening/closing the file.

coordinates stored in a getPoint() object

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());

Manual Positioning of Image in JFrame

I am trying to create a JFrame that displays an image from a file path onto a particular position on the JFrame. At a later time (when a button is clicked), I want the image to move positions, say, 50 pixles to the left. If a layout manager is necessary, I want to use the null layout, as this is a project for myself and I am not quite ready to learn how to write my own layout manager.
So far, I have managed to display a BufferedImage in a frame, but I do not know how to specify its position.
Is using a BufferedImage even the correct approach? What is the best way to go about doing this?
Update: I tried to follow your suggestion of using mouselistener and it resulted in this:
class ImgComponent extends JComponent implements ChangeListener, MouseListener {
MovableImage mi;
public ImgComponent(MovableImage mi) {
this.mi = mi;
mi.addListener(this);
mi.addListener1(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(mi.i, mi.getX(), mi.getY(), null);
}
#Override
public void stateChanged(ChangeEvent e) {
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
mi.setPos(100, 100);
System.out.println("yay");
}
}
But unfortinely, the mouseClicked event never triggers. I just want that damn image to move, lol.
Here's a complete example that uses the model/view/controller pattern. (Just dump all snippets after each other in a single .java file.)
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
// A class encapsulating an image and a x-coordinate (a "model")
class MovableImage {
Image i = new ImageIcon("duke.png").getImage();
private int x = 0;
// Observers that are interested in movements.
List<ChangeListener> listeners = new ArrayList<ChangeListener>();
public void addListener(ChangeListener cl) {
listeners.add(cl);
}
public int getX() {
return x;
}
public void incrementX() {
x += 10;
// Notify those interested.
for (ChangeListener cl : listeners)
cl.stateChanged(null);
}
}
// A graphical component displaying the model.
// Object of this class are interested in movement because when the image moves,
// this component needs to be repainted.
class ImgComponent extends JComponent implements ChangeListener {
// The movable image to present.
MovableImage mi;
public ImgComponent(MovableImage mi) {
this.mi = mi;
mi.addListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(mi.i, mi.getX(), 10, null);
}
// This method is called from MovableImage when the position changes.
#Override
public void stateChanged(ChangeEvent e) {
repaint();
}
}
// Main class.
public class FrameTestBase extends JFrame {
public static void main(String args[]) {
// Create the "model".
final MovableImage mi = new MovableImage();
FrameTestBase t = new FrameTestBase();
t.setLayout(new BorderLayout());
// Add a component presenting the model.
t.add(new ImgComponent(mi), BorderLayout.CENTER);
// Create a button which increments x when clicked on.
t.add(new JButton(new AbstractAction("Move right") {
#Override
public void actionPerformed(ActionEvent e) {
mi.incrementX();
}
}), BorderLayout.SOUTH);
// Show it.
t.setDefaultCloseOperation(EXIT_ON_CLOSE);
t.setSize(400, 400);
t.setVisible(true);
}
}
Regarding your edit:
You need to add the mouse listener as well. In the constructor:
public ImgComponent(MovableImage mi) {
this.mi = mi;
mi.addListener(this);
mi.addListener1(this);
}
add the following line at the bottom:
addMouseListener(this);

Categories