java draw line as the mouse is moved - java

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..

Related

Move and stretch Line2D shape with mouse

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

Drawing shapes in JPanel over an image

I need to draw shapes (circle or free line) over an image that is shown in a JLabel of a JPanel.
I based my code on the questions How to draw thin line with no gap while dragging the cursor? and Draw a circle using 2 mouse clicks.
The code is bellow. The problem is that when I start drawing the image disappears and only reappears after I stop.
If I comment the line super.paintComponent(g); that doesnt happen but when I draw the circle it maintains a path of the previous positions.
public static void main(String args[]) {
try {
URL url = new URL("http://www.senhoritatours.com/wp-content/uploads/2014/05/Porto-.jpg");
backgroundImage = ImageIO.read(url);
} catch (Exception e) {
e.printStackTrace();
}
loadAnnotation();
loadBackground();
JFrame f;
f = new JFrame();
f.setLayout(new BorderLayout());
f.add(mp);
f.pack();
f.setVisible(true);
}
/* Layer 0:
* Load background picture */
public static void loadBackground() {
JLabel lbImg = new JLabel();
lbImg.setBounds(0, 0, new ImageIcon(backgroundImage).getIconWidth(), new ImageIcon(backgroundImage).getIconHeight());
lbImg.setIcon(new ImageIcon(backgroundImage));
mp = new JPanel(new BorderLayout());
btnCircle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if(btnCircle.isEnabled())
{
btnCircle.setEnabled(false);
btnLine.setEnabled(true);
}
}
});
btnLine.setEnabled(true);
btnCircle.setEnabled(false);
btnLine.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if(btnLine.isEnabled())
{
btnLine.setEnabled(false);
btnCircle.setEnabled(true);
}
}
});
mp.add(btnCircle);
mp.add(btnLine);
mp.add(lbImg);
mp.add(p);
}
/* Layer 1:
* Annotation: Draw on top of background picture anything! */
public static void loadAnnotation() {
p = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.RED);
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(1024,600, BufferedImage.TRANSLUCENT);
Graphics2D gc = _bufImage.createGraphics();
}
g2.drawImage(_bufImage, null, 0, 0);
if (_state == State.DRAGGING) {
if (!btnLine.isEnabled())
{
g.drawLine(_start.x, _start.y, _end.x , _end.y);
}
}
if (!btnCircle.isEnabled())
{
g.drawOval(x, y, width, height);
}
}
public Dimension getPreferredSize() {
return new Dimension(1024, 600);
}
};
p.setLayout(new OverlayLayout(p));
p.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mousePressed(MouseEvent me) {
last = me.getPoint();
dragging = isInsideEllipse(last);
if (!dragging) {
x = last.x;
y = last.y;
width = 0;
height = 0;
}
p.repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
//_state = State.IDLE;
last = null;
dragging = false;
_state = State.IDLE;
p.repaint();
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
});
p.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent me) {
if(!btnLine.isEnabled())
{
_state = State.DRAGGING;
_end = me.getPoint();
if (_state == State.DRAGGING) {
Graphics2D g2 = _bufImage.createGraphics();
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(2));
g2.drawLine(_start.x, _start.y, _end.x, _end.y);
p.repaint();
//
}
_start = _end;
}
else
{
int dx = me.getX() - last.x;
int dy = me.getY() - last.y;
if (dragging) {
x += dx;
y += dy;
} else {
width += dx;
height += dy;
}
last = me.getPoint();
p.repaint();
}
}
#Override
public void mouseMoved(MouseEvent me) {
//System.out.println("move");
_start = me.getPoint();
}
});
}
Either
Display the image in the same paintComponent method that you're doing your drawing in, via Graphics#drawImage(...). You would call this immediately after the super.paintComponent(g) call.
Or do your drawing in the paintComponent(...) method of your JLabel, the one displaying the image.
For example:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
private final static String PATH = "https://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/7/7c/Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
+ "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg/"
+ "463px-Thomas_Hicks_-_Leopold_Grozelier_-_Presidential_Candidate_"
+ "Abraham_Lincoln_1860_-_cropped_to_lithographic_plate.jpg";
private static final Color DRAWING_COLOR = new Color(255, 100, 200);
private static final Color FINAL_DRAWING_COLOR = Color.red;
private BufferedImage backgroundImg;
private Point startPt = null;
private Point endPt = null;
private Point currentPt = null;
private int prefW;
private int prefH;
public DrawingPanel() throws IOException {
URL imgUrl = new URL(PATH);
BufferedImage bImg = ImageIO.read(imgUrl);
prefW = bImg.getWidth();
prefH = bImg.getHeight();
backgroundImg = new BufferedImage(prefW, prefH,
BufferedImage.TYPE_INT_ARGB);
Graphics g = backgroundImg.getGraphics();
g.drawImage(bImg, 0, 0, this);
g.dispose();
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseMotionListener(myMouseAdapter);
addMouseListener(myMouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
if (startPt != null && currentPt != null) {
g.setColor(DRAWING_COLOR);
int x = Math.min(startPt.x, currentPt.x);
int y = Math.min(startPt.y, currentPt.y);
int width = Math.abs(startPt.x - currentPt.x);
int height = Math.abs(startPt.y - currentPt.y);
g.drawRect(x, y, width, height);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
public void drawToBackground() {
Graphics g = backgroundImg.getGraphics();
g.setColor(FINAL_DRAWING_COLOR);
int x = Math.min(startPt.x, endPt.x);
int y = Math.min(startPt.y, endPt.y);
int width = Math.abs(startPt.x - endPt.x);
int height = Math.abs(startPt.y - endPt.y);
g.drawRect(x, y, width, height);
g.dispose();
startPt = null;
repaint();
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseDragged(MouseEvent mEvt) {
currentPt = mEvt.getPoint();
DrawingPanel.this.repaint();
}
#Override
public void mouseReleased(MouseEvent mEvt) {
endPt = mEvt.getPoint();
currentPt = null;
drawToBackground();
}
#Override
public void mousePressed(MouseEvent mEvt) {
startPt = mEvt.getPoint();
}
}
private static void createAndShowGui() {
DrawingPanel mainPanel = null;
try {
mainPanel = new DrawingPanel();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("Drawing Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

can't draw on a JPanel after repaint method

I'm experimenting on a GUI that I programmed and I don't understand how I can fix my problem:
My GUI contains a jPanel that on receiving a mouseclick, paints a point with filloval command.
private void myPnlMousePressed(java.awt.event.MouseEvent evt) {
changed = true;
p.x = evt.getX();
p.y = evt.getY();
drewPoints(p.x, p.y);
}
private void drewPoints (int x, int y) {
if (gf == null) {
gf = (Graphics)myPnl.getGraphics();
}
myPointsList.add(new Point(x, y));
gf.fillOval(x, y, 5, 5);
xVal.setText("X = " + x);
yVal.setText("Y = " + y);
}
everything works fine but when I want to open an XML file that I created to save all the points it doesn't work.
The problem is that when I use the repaint method on the jPanel after choosing a file, all the points loads fine but the panel can't draw the points.
If I put the repaint method in the open button listener (before the choosing file) it works, but then if the user cancels the open option so the panel stays blank and I don't want to draw the points again.
I think it happens because the repaint process is not finished.
All the points added to a private List.
private void OpenFile() {
try {
File thisFile;
JFileChooser of = new JFileChooser();
int option = of.showOpenDialog(of);
if (option == JFileChooser.APPROVE_OPTION){
thisFileName = of.getSelectedFile().getPath();
thisFile = new File(thisFileName);
if (!of.getSelectedFile().getName().endsWith(".xml")) {
String error = "Error, You didn't select XML file";
JOptionPane.showMessageDialog(this, error, "Wrong type of file", JOptionPane.INFORMATION_MESSAGE);
return;
}
myPnl.repaint();
myPointsList.clear();
....
....
....
for (int i = 0; i < pointsList.getLength(); i++) {
Element point = (Element) pointsList.item(i);
p.x = Integer.parseInt(point.getElementsByTagName("X").item(0).getTextContent());
p.y = Integer.parseInt(point.getElementsByTagName("Y").item(0).getTextContent());
drewPoints(p.x, p.y);
}
....
how can I make it work??
Don't use gf = (Graphics)myPnl.getGraphics();, this is not how painting in Swing works. The getGraphics method can return null and is nothing more then a snap shot of the last paint cycle, any thing you paint to it will be erased on the next paint cycle (repaint).
Instead, override the JPanels paintComponent and put all you painting logic there. There is an expectation that when called, you are expected to fully re-paint the current state of the component.
See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
You have to use the repaint() and override the paint() method:
class MyPanel extends JPanel implements MouseListener
{
private int x;
private int y;
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 10, 10);
}
}
If you want to draw all points, don't use x and y but a list of points:
class MyPanel extends JPanel implements MouseListener
{
private ArrayList<Point> points = new ArrayList<>();
public MyPanel() {
super();
addMouseListener(this);
}
#Override public void mouseEntered(MouseEvent e) { }
#Override public void mouseExited(MouseEvent e) { }
#Override public void mouseClicked(MouseEvent e) { }
#Override public void mousePressed(MouseEvent e) { }
#Override public void mouseReleased(MouseEvent e) {
points.add(new Point(e.getX(), e.getY()));
repaint();
}
#Override public void paint(Graphics g) {
super.paint(g);
for (Point p : points)
g.fillOval(p.getX(), p.getY(), 10, 10);
}
}
where:
class Point
{
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Then use it:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
MyPanel myPanel = new MyPanel();
frame.add(myPanel);
frame.setVisible(true);
}

How to draw on the JFrame?

I have a pdf file, which is rendered as an image and added as a JLabel in the JFrame. Now i want to draw on the contents in the JFrame by mouseclick and keystrokes. And these drawings should appear on the image(JLabel). I have pasted my code below. Can anyone please help me to figure it out!!!
public class LinePanel extends JPanel{
public static final String RESOURCE = "G:/resource/A0TestFile.pdf";
private MouseHandler mouseHandler = new MouseHandler();
private Point p1;
private Point p2;
private Point p3;
private Point p4;
ArrayList<Point> points = new ArrayList<Point>();
public LinePanel() {
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(1,
BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL));
crop(g);
}
public void crop(Graphics g){
if(points != null && points.size()>0){
for(int i=0;i<points.size();i++){
p1 = points.get(i);
g.drawLine(p1.x, p1.y, p1.x-20, p1.y);
g.drawLine(p1.x, p1.y, p1.x, p1.y+20);
}
for( i=1;i<points.size();i++){
p2 = points.get(i);
g.drawLine(p2.x, p2.y, p2.x-20, p2.y);
g.drawLine(p2.x, p2.y, p2.x, p2.y-20);
}
for( i=2;i<points.size();i++){
p3 = points.get(i);
g.drawLine(p3.x, p3.y, p3.x+20, p3.y);
g.drawLine(p3.x, p3.y, p3.x, p3.y-20);
}
for( i=3;i<points.size();i++){
p4 = points.get(i);
g.drawLine(p4.x, p4.y, p4.x+20, p4.y);
g.drawLine(p4.x, p4.y, p4.x, p4.y+20);
}
}
}
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if(points.size()<4){
points.add(e.getPoint());
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
}
private class ControlPanel extends JPanel {
private static final int DELTA = 1;
public ControlPanel() {
new MoveButton("\u2190", KeyEvent.VK_LEFT, -DELTA, 0);
new MoveButton("\u2191", KeyEvent.VK_UP, 0, -DELTA);
new MoveButton("\u2192", KeyEvent.VK_RIGHT, DELTA, 0);
new MoveButton("\u2193", KeyEvent.VK_DOWN, 0, DELTA);
}
private class MoveButton extends JButton {
KeyStroke k;
int dx, dy;
public MoveButton(String name, int code,
final int dx, final int dy) {
super(name);
this.k = KeyStroke.getKeyStroke(code, 0);
this.dx = dx;
this.dy = dy;
this.setAction(new AbstractAction(this.getText()) {
#Override
public void actionPerformed(ActionEvent e) {
if(points.size()==1){
LinePanel.this.p1.translate(dx, dy);
LinePanel.this.repaint();
}
if(points.size()==2){
LinePanel.this.p2.translate(dx, dy);
LinePanel.this.repaint();
}
if(points.size()==3){
LinePanel.this.p3.translate(dx, dy);
LinePanel.this.repaint();
}
if(points.size()==4){
LinePanel.this.p4.translate(dx, dy);
LinePanel.this.repaint();
}
}
});
ControlPanel.this.getInputMap(WHEN_IN_FOCUSED_WINDOW)
.put(k, k.toString());
ControlPanel.this.getActionMap()
.put(k.toString(), new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
MoveButton.this.doClick();
}
});
}
}
}
private void display() throws IOException{
File file = new File(RESOURCE);
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_WRITE,
0, channel.size());
PDFFile pdffile = new PDFFile(buf);
PDFPage page = pdffile.getPage(1);
Rectangle rect = new Rectangle(0,0,(int)page.getBBox().getWidth(),(int)page.getBBox().getHeight());
Image img = page.getImage(rect.width, rect.height,rect,null,true,true);
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(800, 800));
JPanel panel = new JPanel();
JLabel image = new JLabel(new ImageIcon(img));
panel.add(image);
JScrollPane jspane=new JScrollPane(panel);
f.add(jspane, BorderLayout.CENTER);
f.add(this);
f.add(new ControlPanel(),BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
new LinePanel().display();
} catch (IOException ex) {
Logger.getLogger(LinePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}
Try this. It's a Panel with an Image. Add the Panel to the Frame;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
// draw other stuff
}
}
If you want your drawing to be painted on top of any component added to the panel/frame, you need to override the paint() method.
Take a look at A Closer Look at the Paint Mechanism

Free line drawing java2d app connects lines of each new drawing

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.

Categories

Resources