I want to move and stretch a Line2D shape with mouse. I tried but was facing some issues. While moving it suddenly moves in various directions. I was facing issues with:
shape.setLine(p1,p2);
EDIT:
Earlier I had faced some problems.
But I could make it work now hence thought to post here.
public static void main(String[] args) {
JFrame frame = new JFrame("Lines");
frame.add(new JComponent() {
private Shape line = null;
{
line = new Line2D.Double(100, 100, 200, 200);
prevPoint = new Point();
newPoint = new Point();
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
prevPoint = e.getPoint();
System.out.println("Prev Point=" + prevPoint.toString());
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
int dx = 0;
int dy = 0;
dx = (int) (prevPoint.x - e.getPoint().getX());
dy = (int) (prevPoint.y - e.getPoint().getY());
Line2D shape = (Line2D) line;
int x1 = (int) (shape.getX1() - dx);
int y1 = (int) (shape.getY1() - dy);
int x2 = (int) (shape.getX2() - dx);
int y2 = (int) (shape.getY2() - dy);
Point startPoint = new Point(x1, y1);
Point endPoint = new Point(x2, y2);
if (shape != null) {
shape.setLine(startPoint, endPoint);
prevPoint = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
repaint();
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (line != null) {
g2d.draw(line);
}
}
});
frame.setSize(650, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Thanks
Related
So, I have a program where I can add shapes to JPanel using Path2D objects and then I can click and drag them around. What I want to do is be able to find the final X and Y coordinates of the shape AFTER it has been drug. The coordinates need to be the top-left coordinates. Any ideas?
// add a circle to center of the screen
public void addCircle(int width, int height) {
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
getHeight() / 2 - height / 2, width, height), true);
shapes.add(circ);
repaint();
}
..................
//paint all shapes
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.draw(shape);
}
}
..................
// if the mouse click is in the circle, set pressed=true
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (int i = 0; i < shapes.size(); i++) {
if (shapes.get(i) != null
&& shapes.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
}
}
//if pressed=true, move circle with mouse
#Override
public void mouseDragged(MouseEvent e) {
if (pressed && !lineSelected) {
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
//I need to find the new coordinates here!!!!!!!!!!!
repaint();
}
}
Full Code
class Canvas extends JPanel {
private static final long serialVersionUID = 1L;
private List<Path2D> shapes = new ArrayList<Path2D>();
private int currentIndex;
private Point lineStartingPoint = new Point();
private Point lineEndingPoint = new Point();
private boolean drawing;
private boolean lineSelected;
private Path2D.Double linePath;
private Shapes myShapes = new Shapes();
private List<Path2D> circles = new ArrayList<Path2D>();
public Canvas() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
public void setList(ArrayList<UMLCircle> shapes) {
}
public List<UMLCircle> getList() {
return null;
}
public void addSquare(int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
shapes.add(rect2);
repaint();
}
public void addLine() {
lineSelected = true;
repaint();
}
public void addCircle(int width, int height) {
myShapes.addCircle(getWidth() / 2 - width / 2, getHeight() / 2 - height
/ 2, width, height);
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
getHeight() / 2 - height / 2, width, height), true);
circles.add(circ);
shapes.add(circ);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
if (lineSelected) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(2));
g2.drawLine(lineStartingPoint.x, lineStartingPoint.y,
lineEndingPoint.x, lineEndingPoint.y);
}
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.draw(shape);
}
}
class MyMouseAdapter extends MouseAdapter {
private boolean pressed = false;
private Point point;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (int i = 0; i < shapes.size(); i++) {
if (shapes.get(i) != null
&& shapes.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
if (circles.get(i) != null
&& circles.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
}
if (lineSelected) {
drawing = true;
lineStartingPoint = e.getPoint();
lineEndingPoint = lineStartingPoint;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed && !lineSelected) {
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
myShapes.updateCircleLocation(currentIndex, point.x, point.y);
System.out.println(point.x + " " + point.y);
repaint();
}
if (drawing) {
lineEndingPoint = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (drawing && lineSelected) {
drawing = false;
lineSelected = false;
lineEndingPoint = e.getPoint();
linePath = new Path2D.Double();
linePath.moveTo(lineStartingPoint.getX(),
lineStartingPoint.getY());
linePath.lineTo(lineEndingPoint.getX(), lineEndingPoint.getY());
shapes.add(linePath);
repaint();
}
pressed = false;
}
}
}
EDIT
Calculation for offset:
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
int newXPos = e.getX() - deltaX; // final X pos
int newXPos = e.getX() - deltaX; // final Y pos
Before you can do anything, you need to know the offset of the mouse click from the corner of the shape, this will allow you to drag the object so it doesn't suddenly "jump" to your current mouse position...
#Override
public void mousePressed(MouseEvent e) {
//...
for (Shape shape : myShapes) {
//...
this.point = e.getPoint();
int deltaX = point.x - shape.getBounds().x;
int deltaY = point.y - shape.getBounds().y;
offset = new Point(deltaX, deltaY);
//...
}
}
}
Then, you would calculate the delta of change, between the current mouse position and the offset. Because you're applying a translate, you also need to subtract the shape's current location, as the translation is based on the shape's current location and we only want to apply the amount of change
#Override
public void mouseDragged(MouseEvent e) {
if (pressed) {
int index = myShapes.indexOf(clickedShape);
myShapes.remove(index);
int deltaX = e.getPoint().x - offset.x;
int deltaY = e.getPoint().y - offset.y;
clickedShape = new Path2D.Double(clickedShape,
AffineTransform.getTranslateInstance(
deltaX - clickedShape.getBounds().x,
deltaY - clickedShape.getBounds().y));
myShapes.add(index, clickedShape);
point = e.getPoint();
repaint();
}
}
Now, having said all that, don't do this...
protected void paintComponent(Graphics g) {
//...
this.setOpaque(true);
this.setBackground(Color.WHITE);
Changing the state of the component from within the paint method can setup a infinite loop of repaint requests, which can chock your system. Also, the changes you make won't be applied to the current graphics context, as these properties are generally applied by the paint method...
And a working copy....
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
class Canvas extends JPanel {
private static final long serialVersionUID = 1L;
private boolean drawing;
private List<Shape> myShapes = new ArrayList<Shape>();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Canvas());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public Canvas() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
addSquare(100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void setList(ArrayList<Shape> shapes) {
}
public List<Shape> getList() {
return null;
}
public void addSquare(int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
myShapes.add(rect2);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Shape shape : myShapes) {
g2.draw(shape);
}
}
class MyMouseAdapter extends MouseAdapter {
private boolean pressed = false;
private Point point;
private Point offset;
private Shape clickedShape;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (Shape shape : myShapes) {
if (shape != null
&& shape.contains(e.getPoint())) {
System.out.println("Clicked");
pressed = true;
clickedShape = shape;
this.point = e.getPoint();
int deltaX = point.x - shape.getBounds().x;
int deltaY = point.y - shape.getBounds().y;
offset = new Point(deltaX, deltaY);
System.out.println(point + "x" + offset);
repaint();
break;
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed) {
int index = myShapes.indexOf(clickedShape);
myShapes.remove(index);
int deltaX = e.getPoint().x - offset.x;
int deltaY = e.getPoint().y - offset.y;
clickedShape = new Path2D.Double(clickedShape,
AffineTransform.getTranslateInstance(
deltaX - clickedShape.getBounds().x,
deltaY - clickedShape.getBounds().y));
myShapes.add(index, clickedShape);
point = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
offset = null;
pressed = false;
}
}
}
I'm making a music/drawing application which you free draw lines with your mouse and a TrackBar passes horizontally through it and reads the lines and uses the x and y coordinate to modify music.
The problem I'm having is that TrackBar class is a JPanel and DrawBoard class is a JPanel which I add inside a Frame. But which ever is on-top is the one that will show, what I want is for them to both show, and the TrackBar to pass on top of the lines drawn.
Below Is the source code of this 3 classes and took out some unncesesary code:
The MainFrame class where I add them (with the current setup the TrackBar doesnt appear but the Drawing board appears since it overlaps it):
public class MainFrame extends JFrame {
public static ColourToolbar colourBar;
public static TrackBar tb;
public MainFrame(){
super("VIPE by Prestige WorldWide");
// Top colour toolbar for tones
colourBar = new ColourToolbar();
this.getContentPane().add(colourBar, BorderLayout.NORTH);
// This class ImagePanel is a JPanel which I overite the paintCOmponent to have background
ImagePanel bg = new ImagePanel();
bg.setLayout(new BorderLayout());
Dimension size = getPreferredSize();
size.setSize(1024,800); //w, h
bg.setPreferredSize(size);
this.getContentPane().add(bg, BorderLayout.CENTER);
// I add the TrackBar to the ImagePanel since its the Background
tb = new TrackBar();
bg.add(tb, BorderLayout.CENTER);
// I add the drawing board but It will overlap the Trackbar
DrawBoard dboard = new DrawBoard();
bg.add(dboard, BorderLayout.CENTER);
// The control toolbar where the settings and control buttons are.
Toolbar toolBar = new Toolbar();
this.getContentPane().add(toolBar, BorderLayout.SOUTH);
}
public static void main(String[] args){
MainFrame frame = new MainFrame();
frame.setBackground(Color.WHITE);
frame.setSize(1024,768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//frame.pack();
frame.setVisible(true);
}
}
Now the TrackBar class:
public class TrackBar extends JPanel{
private TrackBarAction tba = new TrackBarAction(this);
public static int TIME = 9;
public Timer t = new Timer(TIME, tba);
public static double x = 0, y = 0, velX = 1.0, velY = 0;
private int SKIP = 120;
public TrackBar(){
this.setOpaque(false);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
//g2d.drawRect((int)x, (int)y, 10, 800);
Rectangle2D r2d = new Rectangle2D.Double(x, y, 8.0, 800.0); // x,x, w, h
g2d.setPaint(Color.DARK_GRAY);
g2d.fill(r2d);
g2d.draw(r2d);
}
public void reset(){
t.stop();
x = 0;
y = 0;
velX = 0.5;
velY = 0;
this.repaint();
}
public void skipForward(){
if(x+SKIP <= 1024){
x += SKIP;
} else {
x = 1024 - x;
}
this.repaint();
}
public void skipBackwards(){
if(x-SKIP >= 0){
x -= SKIP;
} else {
x = 0;
}
this.repaint();
}
}
And now the DrawBoard class:
public class DrawBoard extends JPanel implements MouseListener, MouseMotionListener{
(..)
public Color currentColor;
public static boolean eraser = false;
private int xX1, yY1;
public DrawBoard(){
Graphics2D g2d = bImage.createGraphics();
g2d.dispose();
Dimension size = getPreferredSize();
size.setSize(1024,800); //w, h
setPreferredSize(size);
//status = new JLabel("default");
//add(status, BorderLayout.SOUTH);
addMouseListener(this);
addMouseMotionListener(this);
imgLabel = new JLabel(new ImageIcon(bImage)) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintInLabel(g);
}
};
imgLabel.setOpaque(false);
setOpaque(false);
add(imgLabel, BorderLayout.CENTER);
}
private void paintInLabel(Graphics g) {
if(!eraser){
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getColor()); // this colour is when mouse is pressed
g2d.setStroke(new BasicStroke(STROKESIZE));
if (points.size() < 1) {
return;
}
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
}
// Where the drawing happens
#Override
public void mousePressed(MouseEvent e) {
//status.setText("you pressed down the mouse");
if(!eraser){
xX1 = e.getX();
yY1 = e.getY();
points.add(e.getPoint());
}
}
#Override
public void mouseDragged(MouseEvent e) {
//status.setText("you draged the mouse");
Graphics2D g2d = bImage.createGraphics();
// this is the eraser code
if(eraser){
//Graphics2D g2d = bImage.createGraphics();
System.out.println("eraser = true");
System.out.println("Stroke = " + STROKESIZE);
g2d.setComposite(AlphaComposite.Clear);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.drawRect(e.getX(), e.getY(), STROKESIZE, STROKESIZE);
g2d.fillRect(e.getX(), e.getY(), STROKESIZE, STROKESIZE);
// g2d.setColor(c);
imgLabel.repaint();
}else {
//g2d.setComposite();
points.add(e.getPoint());
System.out.println("point = " + e.getPoint());
imgLabel.repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
//status.setText("you release the mouse click");
if(!eraser){
Graphics2D g2d = bImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getColor()); // this is the final colour
g2d.setStroke(new BasicStroke(STROKESIZE));
if (points.size() >= 2) {
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
g2d.dispose();
points.clear();
imgLabel.repaint();
}
//imgLabel.repaint();
}
// End of where the drawing happens
public void clearDrawBoard() {
}
private Color getColor() {
return ColourToolbar.selectedColor;
}
private void setColor(Color col){
this.currentColor = col;
}
#Override
public void mouseClicked(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}
BorderLayout can only have one component add to each of it a 5 positions. By adding the DrawPanel to the center position, you are effectively removing the TrackPanel.
Instead, set the layout manager of the TrackBar to BorderLayout and add the DrawPanel to it.
You could also use a JLayeredPane, but the management becomes more involved
I'm building an app that recognises lines drawn with mouse and creates music. I'm new to java2d so heres the problem i'm having:
When you draw, and then make another drawing, the last point of the previous drawing connects to the first of the new one. I havent been able to figure out how to fix this. Below is the code.
Another question is: I would like to store each stroke of drawing (from mousePressed to mouseReleased) into a ArrayList of type Shape, how can I go into that?
I'd like to be pointed in the right direction as I havent been able to find helpful info online. Thanks!
public class DrawBoard extends JPanel implements MouseListener,
MouseMotionListener {
public JLabel status;
public Point pstart, pfinish;
private Shape currentShape = null;
private ArrayList<Point> points = new ArrayList<Point>();
private ArrayList<Shape> lines = new ArrayList<Shape>();
public DrawBoard() {
Dimension size = getPreferredSize();
size.setSize(1024, 800); // w, h
setPreferredSize(size);
setOpaque(false);
status = new JLabel("default");
add(status, BorderLayout.SOUTH);
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
status.setText(String.format("Clicked at %d,%d", e.getX(), e.getY()));
}
// Where the drawing happens
#Override
public void mousePressed(MouseEvent e) {
status.setText("you pressed down the mouse");
this.pstart = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e) {
status.setText("you draged the mouse");
points.add(e.getPoint());
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
status.setText("you release the mouse click");
pfinish = e.getPoint();
}
// End of where the drawing happens
#Override
public void mouseEntered(MouseEvent e) {
status.setText("you entered the area");
}
#Override
public void mouseExited(MouseEvent e) {
status.setText("mouse exited the area");
}
#Override
public void mouseMoved(MouseEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(5));
for (int i = 0; i < points.size() - 2; i++) {
Point p1 = points.get(i);
Point p2 = points.get(i + 1);
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
}
I have modified it using BufferedImage and it works for drawing normally, now the only thing does nto work is the clear method, i have tried different methods but none have worked. My new code is Below:
public class DrawBoard extends JPanel implements MouseListener, MouseMotionListener{
public JLabel status;
private JLabel imgLabel;
public Point pstart, pfinish;
private Shape currentShape = null;
private List<Point> points = new ArrayList<Point>();
private List<BufferedImage> lines = new ArrayList<BufferedImage>();
private static final int BI_WIDTH = 1024;
private static final int BI_HEIGHT = 800;
private BufferedImage bImage = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
public DrawBoard(){
Graphics2D g2d = bImage.createGraphics();
g2d.dispose();
Dimension size = getPreferredSize();
size.setSize(1024,800); //w, h
setPreferredSize(size);
status = new JLabel("default");
add(status, BorderLayout.SOUTH);
addMouseListener(this);
addMouseMotionListener(this);
imgLabel = new JLabel(new ImageIcon(bImage)) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintInLabel(g);
}
};
imgLabel.setOpaque(false);
setOpaque(false);
add(imgLabel, BorderLayout.CENTER);
}
private void paintInLabel(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE); // this colour is when mouse is pressed
g2d.setStroke(new BasicStroke(5));
if (points.size() < 2) {
return;
}
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
#Override
public void mouseClicked(MouseEvent e) {
status.setText(String.format("Clicked at %d,%d", e.getX(), e.getY()));
}
// Where the drawing happens
#Override
public void mousePressed(MouseEvent e) {
status.setText("you pressed down the mouse");
this.pstart = e.getPoint();
points.add(e.getPoint());
}
#Override
public void mouseDragged(MouseEvent e) {
status.setText("you draged the mouse");
points.add(e.getPoint());
imgLabel.repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
status.setText("you release the mouse click");
Graphics2D g2d = bImage.createGraphics();
g2d.setColor(Color.blue); // this is the final colour
g2d.setStroke(new BasicStroke(5));
if (points.size() >= 2) {
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
g2d.dispose();
points.clear();
imgLabel.repaint();
}
// End of where the drawing happens
#Override
public void mouseEntered(MouseEvent e) {
status.setText("you entered the area");
}
#Override
public void mouseExited(MouseEvent e) {
status.setText("mouse exited the area");
}
#Override
public void mouseMoved(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
public void clearDrawBoard() {
imgLabel.setIcon(null);
}
}
A few solutions and suggestions:
Don't draw from a single List<Point> as there's no way of knowing where one line ends and another begins.
Consider drawing each line to a BufferedImage once it is complete and display that BufferedImage in your JComponent in its paintComponent method. You would place it in the BufferedImage in the mouseReleased(...) method.
Or consider creating an List<List<Point>> so you can iterate through each line as needed. You would add the new List<Point> to the original List in the mouseReleased(...) method.
Consider using your List<Shape> and fill it with Line2D objects that can be drawn. The Line2D would be added to the List<Shape> in the mouseReleased(...) method.
Also: You should not override paint(...) but rather `paintComponent(...).
Also: Don't forget the #Override annotation for safer coding.
For example, please see my code and answer here.
I would like to add a feature to my application which allows the user to draw a straight line by clicking the mouse at the start location and releasing it at the end location. The line should move as the mouse moves until it is finally released; similar to the way that a line can be drawn using the Microsoft Paint application.
How can implement this so that the line is repainted as it moves without repainting other things that may already be drawn in that rectangular area?
Try this...Draw a red line on the screen as the mouse is moved (dragged).
public static void main(String args[]) throws Exception {
JFrame f = new JFrame("Draw a Red Line");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
JPanel p = new JPanel() {
Point pointStart = null;
Point pointEnd = null;
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
pointEnd = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
repaint();
}
});
}
public void paint(Graphics g) {
super.paint(g);
if (pointStart != null) {
g.setColor(Color.RED);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
};
f.add(p);
f.setVisible(true);
}
The MouseListener interface is your friend for this. You can just implement mousePressed and mouseReleased functions. The MouseListener interface has the following methods that you can play around with:
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
JFrame frame = new JFrame("Lines");
frame.add(new JComponent() {
private Shape line = null;
{
line = new Line2D.Double(100, 100, 200, 200);
prevPoint = new Point();
newPoint = new Point();
MouseAdapter mouseAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
prevPoint = e.getPoint();
System.out.println("Prev Point=" + prevPoint.toString());
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
int dx = 0;
int dy = 0;
dx = (int) (prevPoint.x - e.getPoint().getX());
dy = (int) (prevPoint.y - e.getPoint().getY());
Line2D shape = (Line2D) line;
int x1 = (int) (shape.getX1() - dx);
int y1 = (int) (shape.getY1() - dy);
int x2 = (int) (shape.getX2() - dx);
int y2 = (int) (shape.getY2() - dy);
Point startPoint = new Point(x1, y1);
Point endPoint = new Point(x2, y2);
if (shape != null) {
shape.setLine(startPoint, endPoint);
prevPoint = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
repaint();
}
};
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if (line != null) {
g2d.draw(line);
}
}
});
frame.setSize(650, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This will move the line as the mouse is moved..
Hope this helps..
I want to Zoom specific area on image. which is selected by the user. image display on canvas using Swing. i already done full image zoom on canvas but can't implement specific area zoom.
please help
Canvas is awt not swing. Try JPanel instead. Example.
But if you already done full image zoom, try to make the same on a sub-image.
BufferedImage.getSubimage(x, y, w, h);
EDIT
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Example {
private Point startPoint = new Point(0, 0);
private Point rectLocale = new Point();
private Dimension rectSize = new Dimension();
private int zoom = 80;
private BufferedImage capture = null;
private BufferedImage raw;
public Example() throws Exception {
raw = new Robot().createScreenCapture(new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize()));
MouseBehavior behavior = new MouseBehavior();
JPanel b = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(500, 500);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = ((Graphics2D) g);
g2d.drawImage(raw, 0, 0, null);
if (capture != null) {
int width2 = (int) (rectSize.width + rectSize.width * (zoom / 500d));
int height2 = (int) (rectSize.height + rectSize.height * (zoom / 500d));
int x2 = rectLocale.x - ((width2 - rectSize.width) / 2);
int y2 = rectLocale.y - ((height2 - rectSize.height) / 2);
Image scaledInstance = capture.getScaledInstance(
width2, height2, Image.SCALE_AREA_AVERAGING);
g2d.drawImage(scaledInstance, x2, y2, null);
g2d.drawRect(x2, y2, width2, height2);
} else {
g2d.draw(new Rectangle(rectLocale, rectSize));
}
}
};
b.addMouseMotionListener(behavior);
b.addMouseListener(behavior);
b.addMouseWheelListener(behavior);
JFrame f = new JFrame();
f.setLocation(10, 10);
f.setDefaultCloseOperation(3);
f.add(b);
f.pack();
f.setVisible(true);
}
private class MouseBehavior extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
rectLocale = new Point();
rectSize = new Dimension();
capture = null;
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point currentPoint = e.getPoint();
rectSize.width = Math.abs(currentPoint.x - startPoint.x);
rectSize.height = Math.abs(currentPoint.y - startPoint.y);
if (e.isShiftDown()) {
rectSize.width = rectSize.height = Math.min(
rectSize.width, rectSize.height);
int dx = startPoint.x - rectSize.width;
int dy = startPoint.y - rectSize.height;
rectLocale.x = startPoint.x < currentPoint.x ? startPoint.x
: Math.max(dx, dy);
rectLocale.y = startPoint.y < currentPoint.y ? startPoint.y
: Math.min(dx, dy);
} else {
rectLocale.x = Math.min(currentPoint.x, startPoint.x);
rectLocale.y = Math.min(currentPoint.y, startPoint.y);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rectSize.width <= 0 || rectSize.height <= 0) {
capture = null;
} else {
capture = raw.getSubimage(Math.max(0, rectLocale.x),
Math.max(0, rectLocale.y), rectSize.width, rectSize.height);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
zoom = Math.min(2000, Math.max(0, zoom + e.getUnitsToScroll() * 10));
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Example example = new Example();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}