Currently, I'm working on my first Java application with which a user can look through photos, cut them and rotate. I have an issue with clipping an image. What I want to achieve is the following:
User clicks on the "Cut" option
Rectangle shape called by repaint method appears on the image
By stretching the rectangle user chooses the area for cutting
When the user releases the mouse(which stops stretching the rectangle) the area that is surrounded with the rectangle is left and all the rest of the image is cut.
As of for now I have several issues:
My image is centralized on JLabel which in its turn is added to JPanel and the last is added to JFrame, so now, when I want to add a rectangle above JLable (so it is to be located on the picture) it's invisible and is added only on JPanel directly.
I drew an image with paintComponent but can't figure out how to move and stretch it and repaint the rectangle again.
Below is the part of my code which (I hope) will describe my problems more precisely:
public class GraphicalUserInterface {
static JPanel background;
static JLabel labelIcon;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GraphicalUserInterface().go();
}
});
}
public void go() {
buildGui();
}
public void buildGui() {
frame = new JFrame("PicMove");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BorderLayout layout = new BorderLayout();
background = new JPanel(layout);
/**To center picture on the background**/
labelIcon = new JLabel();
labelIcon.setHorizontalAlignment(JLabel.CENTER);
labelIcon.setVerticalAlignment(JLabel.CENTER);
background.add(BorderLayout.SOUTH, bottom);
background.add(BorderLayout.PAGE_START, bar);
background.add(BorderLayout.CENTER, labelIcon);
background.add(BorderLayout.EAST, chatPanel);
frame.getContentPane().add(BorderLayout.CENTER, background);
frame.setJMenuBar(menuBar);
frame.setVisible(true);
frame.setSize(1300, 1200);}
static class CutImage extends JPanel implements Runnable {
boolean clip;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (clip) {
BasicStroke bs = new BasicStroke(50, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
10, null, 0);
g2d.setStroke(bs);
QuadCurve2D.Float qc = new QuadCurve2D.Float(20, 50, 100, 140, 460, 170);
g2d.setClip(qc);
}
BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
10, new float[]{10}, 0);
g2d.setStroke(bs);
g2d.drawRect(260, 50, 80, 120);
}
#Override
public void run() {
CutImage cutPanel = new CutImage();
GraphicalUserInterface.background.add(cutPanel).repaint();
}
}
public class PicChanges implements Runnable{
static BufferedImage newImage;
static File [] selectedFile;
static int currentImage;
FileNameExtensionFilter filter;
JFileChooser fileChooser;
public void openPic() {
currentImage = 0;
try {
fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(new java.io.File((System.getProperty("user.home"))));
filter = new FileNameExtensionFilter("*.images", "jpg", "gif", "png");
fileChooser.addChoosableFileFilter(filter);
fileChooser.setMultiSelectionEnabled(true);
int result = fileChooser.showOpenDialog(null);
if (result == JFileChooser.OPEN_DIALOG) {
selectedFile = fileChooser.getSelectedFiles();
for (File image : selectedFile) {
if ((image.isFile()) && (selectedFile.length > 0)){
newImage = ImageIO.read(selectedFile[0]);
GraphicalUserInterface.labelIcon.setIcon(new ImageIcon(
new ImageIcon(newImage).getImage().getScaledInstance(
450, 620, Image.SCALE_DEFAULT)));
} else if (result == JFileChooser.CANCEL_OPTION) {
System.out.println("No Pics Selected");
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
Thread.currentThread().interrupt();
openPic();
}
public static void nextPic() {
currentImage++;
try {
newImage = ImageIO.read(selectedFile[currentImage]);
} catch (IOException e) {
e.printStackTrace();
System.out.println("No pictures left");
System.out.println("next"+currentImage);
}
GraphicalUserInterface.labelIcon.setIcon(new ImageIcon(
new ImageIcon(newImage).getImage().getScaledInstance(
450, 620, Image.SCALE_DEFAULT)));
}
static class NextPicture implements Runnable{
#Override
public void run() {
Thread.currentThread().interrupt();
nextPic();
}
}
public static void previousPic () {
currentImage--;
try {
newImage = ImageIO.read(selectedFile[currentImage]);
} catch (IOException e) {
e.printStackTrace();
System.out.println("previous "+currentImage);
}
GraphicalUserInterface.labelIcon.setIcon(new ImageIcon(
new ImageIcon(newImage).getImage().getScaledInstance(
450, 620, Image.SCALE_DEFAULT)));
}
static class PreviousPic implements Runnable{
#Override
public void run() {
Thread.currentThread().interrupt();
previousPic();
}
}
}
My idea was to add MouseListeners but can I add it to the shape created with Graphics2D?
I would be greatful for the help :)
Thank you
Being in search of finding a solution to this question I've asked two more questions(maybe it will be helpful for someone) :
1) Why BufferedImage is not cut according to the drawn in paintComponent method rectangle(its height is calculated wrong)?
2) Repaint() method doesn't invoke paint() & paintComponent() methods one by one, only paintComponent () method is working
that further helped me to find out the way.
My solution is to create a separate frame for displaying copied BufferedImage in it and on this frame to draw a rectangle with the help of MouseListeners. This is the piece of code:
public class ImageScreenShot extends JFrame implements MouseListener, MouseMotionListener {
#Override
public Dimension getPreferredSize() {
return super.getPreferredSize();
}
private static Thread screenShotThread;
public static Thread getScreenShotThread() {
return screenShotThread;
}
public static void setScreenShotThread(Thread screenShot) {
ImageScreenShot.screenShotThread = screenShot;
}
private int drag_status = 0, c1, c2, c3, c4;
public int getC1() {
return c1;
}
public int getC2() {
return c2;
}
public int getC3() {
return c3;
}
public int getC4() {
return c4;
}
class AdditionalPanel extends JLabel {
private BufferedImage img;
public BufferedImage getImg() {
return img;
}
public AdditionalPanel(BufferedImage img) {
this.img = img;
setPreferredSize(new Dimension(2560, 1600));
getPreferredSize();
setLayout(null);
}
#Override
public Dimension getPreferredSize() {
return super.getPreferredSize();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
System.out.println("Additional panel class paint method was invoked");
}
}
public void cut() {
AdditionalPanel apanel = new AdditionalPanel(PicChanges.getNewImage());
JScrollPane scrollPane = new JScrollPane(apanel);
scrollPane.addMouseMotionListener(this);
scrollPane.addMouseListener(this);
getContentPane().add(scrollPane, BorderLayout.CENTER);
setPreferredSize(new Dimension(2560, 1600));
getPreferredSize();
pack();
setVisible(true);
}
private void draggedScreen() throws Exception {
int w = c1 - c3;
int h = c2 - c4;
w = w * -1;
h = h * -1;
Robot robot = new Robot();
BufferedImage img = robot.createScreenCapture(new Rectangle(c1, c2, w, h));
File save_path = new File("screen1.jpg");
ImageIO.write(img, "JPG", save_path);
GraphicalUserInterface.getLabelIcon().setIcon(new ImageIcon(new ImageIcon(img).getImage().getScaledInstance(img.getWidth(), img.getHeight(), Image.SCALE_SMOOTH)));
JOptionPane.showConfirmDialog(this, "Would you like to save your cropped Pic?");
System.out.println("Cropped image saved successfully.");
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
repaint();
c1 = arg0.getXOnScreen();
c2 = arg0.getYOnScreen();
System.out.println("pressed");
}
#Override
public void mouseReleased(MouseEvent arg0) {
repaint();
if (drag_status == 1) {
c3 = arg0.getXOnScreen();
c4 = arg0.getYOnScreen();
try {
repaint();
draggedScreen();
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
repaint();
drag_status = 1;
c3 = arg0.getXOnScreen();
c4 = arg0.getYOnScreen();
}
#Override
public void mouseMoved(MouseEvent arg0) {
}
#Override
public void paint(Graphics g) {
super.paint(g);
int w = c1 - c3;
int h = c2 - c4;
w = w * -1;
h = h * -1;
if (w < 0)
w = w * -1;
g.setColor(Color.RED);
g.drawRect(c1, c2, w, h);
System.out.println("Paint component was invoked in imagescreenshot class");
}
P.S. I know that adding JFrame is not the best solution but I'm still in search for the best way to implement it so do not hesitate to comment on my code and tell what is wrong or what is good)
Related
I write an application with the ability for the user to cut images.
Currently, the code below cut the image a little bit above the drawn rectangle(whose purpose is to show with which coordinates the user wants to cut the image, actually.)
public class ScreenCaptureRectangle extends JFrame implements MouseListener, MouseMotionListener {
int drag_status = 0, c1, c2, c3, c4;
public void cut() {
ImagePanel im = new ImagePanel(PicChanges.getNewImage());
JScrollPane scrollPane = new JScrollPane(im);
add(scrollPane);
setSize(500, 400);
setVisible(true);
im.addMouseListener(this);
im.addMouseMotionListener(this);
}
public void draggedScreen() throws Exception {
int w = c1 - c3;
int h = c2 - c4;
w = w * -1;
h = h * -1;
Robot robot = new Robot();
BufferedImage img = robot.createScreenCapture(new Rectangle(c1, c2, w, h));
File save_path = new File("screen1.jpg");
ImageIO.write(img, "JPG", save_path);
System.out.println("Cropped image saved successfully.");
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
repaint();
c1 = arg0.getX();
c2 = arg0.getY();
}
#Override
public void mouseReleased(MouseEvent arg0) {
repaint();
if (drag_status == 1) {
c3 = arg0.getX();
c4 = arg0.getY();
try {
repaint();
draggedScreen();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Issue is under construction");
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
repaint();
drag_status = 1;
c3 = arg0.getX();
c4 = arg0.getY();
}
#Override
public void mouseMoved(MouseEvent arg0) {
}
public void paint(Graphics g) {
super.paint(g);
int w = c1 - c3;
int h = c2 - c4;
w = w * -1;
h = h * -1;
if (w < 0)
w = w * -1;
g.setColor(Color.RED);
g.drawRect(c1, c2, w, h);
}
public class ImagePanel extends JPanel {
private BufferedImage imageToCut;
public ImagePanel(BufferedImage img) {
this.imageToCut = img;
Dimension size = new Dimension(imageToCut.getWidth(null), imageToCut.getHeight(null));
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
setSize(size);
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(imageToCut, 0, 0, null);
}
}
As of for now when the user crops image like this:
He gets this:
My target is to get the following result:
I use mouse listeners so to get the coordinates of the drawn rectangle and then using these coordinates cut the image. Now the image is cut with incorrect height(as I see it).
I would appreciate it if anyone could tell me what can be wrong in the code?
Thanks!
Thanks to the recommendations I received, now I don't open a separate frame for a photo to cut after a user clicks on the Cut button, I just add MouseListeners to JFrame, which is more convenient and user-friendly. The photo is cut correctly, according to the coordinates from the MouseListeners:
public class ImageScreenShot extends JFrame implements MouseListener, MouseMotionListener {
int drag_status = 0, c1, c2, c3, c4;
public int getC1() {
return c1;
}
public int getC2() {
return c2;
}
public int getC3() {
return c3;
}
public int getC4() {
return c4;
}
public void cut() {
GraphicalUserInterface.getFrame().addMouseMotionListener(this);
GraphicalUserInterface.getFrame().addMouseListener(this);
}
public void draggedScreen() throws Exception {
int w = c1 - c3;
int h = c2 - c4;
w = w * -1;
h = h * -1;
Robot robot = new Robot();
BufferedImage img = robot.createScreenCapture(new Rectangle(c1, c2, w, h));
File save_path = new File("screen1.jpg");
ImageIO.write(img, "JPG", save_path);
GraphicalUserInterface.getLabelIcon().setIcon(new ImageIcon(new ImageIcon(img).getImage().getScaledInstance(img.getWidth(), img.getHeight(), Image.SCALE_SMOOTH)));
JOptionPane.showConfirmDialog(null, "Would you like to save your cropped Pic?");
if (JOptionPane.YES_OPTION == 0) {
/**Need to implement some code*/
} else {
/**Need to implement some code*/
}
System.out.println("Cropped image saved successfully.");
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
c1 = arg0.getXOnScreen();
c2 = arg0.getYOnScreen();
}
#Override
public void mouseReleased(MouseEvent arg0) {
if (drag_status == 1) {
c3 = arg0.getXOnScreen();
c4 = arg0.getYOnScreen();
try {
draggedScreen();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Issue is under construction");
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
drag_status = 1;
c3 = arg0.getXOnScreen();
c4 = arg0.getYOnScreen();
}
#Override
public void mouseMoved(MouseEvent arg0) {
}
I am attempting to have an image show up through file path. I have the image in my src folder, and I've tried maybe 5 different types of code.
Ignore the commented out code, those are just shapes i was drawing to test
I've tried it with both file path and file name and nothing has worked. Its not giving me any errors or anything either.
public void ImagePanel() {
try {
image = ImageIO.read(new File("BMan.jpg"));
} catch (IOException ex) {
System.out.println(ex);
}
}
public static void main(String[] args) {
JPanel panel = new MyPanel();
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
//g.setColor(Color.RED);
//g.fillOval(CircleX, CircleY, CircleH, CircleW);
//g.setColor(Color.GREEN);
//g.fillRect(SquareX, SquareY, SquareW, SquareH);
g.drawImage(image, 50, 50, this);
}
Here is my implementation of the component:
public class ImageView extends JComponent
implements ComponentListener {
private static final long serialVersionUID = 3761966077344495154L;
private BufferedImage image;
private int imageX;
private int imageY;
private int imageWidth;
private int imageHeight;
/** Creates a new instance of ImageView */
public ImageView() {
addComponentListener(this);
}
public BufferedImage getImage() {
return image;
}
public Rectangle getImageBounds() {
if (image == null) {
return null;
} else {
return new Rectangle(imageX, imageY, imageWidth, imageHeight);
}
}
public void setImage(final BufferedImage newValue) {
image = newValue;
computeBounds();
repaint();
}
#Override
public void paint(Graphics g) {
long tm = System.currentTimeMillis();
if (isOpaque()) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
BufferedImage img = image;
if (img != null) {
g.drawImage(img, imageX, imageY, imageWidth, imageHeight, null);
}
tm = System.currentTimeMillis()-tm;
}
public void componentResized(ComponentEvent e) {
computeBounds();
}
public void componentMoved(ComponentEvent e) {
}
public void componentShown(ComponentEvent e) {
computeBounds();
}
public void componentHidden(ComponentEvent e) {
}
private void computeBounds() {
BufferedImage img = image;
if (img != null) {
int width = this.getWidth();
int height = this.getHeight();
int wi = img.getWidth();
int hi = img.getHeight();
imageWidth = width;
imageHeight = height;
imageX = 0;
imageY = 0;
if (wi*height < hi*width) {
imageWidth = wi*height/hi;
imageX = (width-imageWidth)/2;
} else {
imageHeight = hi*width/wi;
imageY = (height-imageHeight)/2;
}
}
}
You need to create a JFrame where you will put the panel:
public static void main(String[] args) {
JFrame frame = new JFrame("title");
frame.setSize(400,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//all the other things for the jframe
JPanel panel = new MyPanel();
frame.add(panel);
frame.setVisible(true);
frame.repaint();
}
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();
}
});
}
}
I have to develop a whiteboard application in which both the local user and the remote user should be able to draw simultaneously, is this possible? If possible then any logic?
I have already developed a code but in which i am not able to do this, when the remote user starts drawing the shape which i am drawing is being replaced by his shape and co-ordinates.
This problem is only when both draw simultaneously.
any idea guys?
Here is my code
class Paper extends JPanel implements MouseListener,MouseMotionListener,ActionListener
{
static BufferedImage image;
int bpressed;
Color color;
Point start;
Point end;
Point mp;
Button elipse=new Button("elipse");
Button rectangle=new Button("rect");
Button line=new Button("line");
Button empty=new Button("");
JButton save=new JButton("Save");
JButton erase=new JButton("Erase");
String selected;
int ex,ey;//eraser
DatagramSocket dataSocket;
JButton button = new JButton("test");
Client client;
Point p=new Point();
int w,h;
public Paper(DatagramSocket dataSocket)
{
this.dataSocket=dataSocket;
client=new Client(dataSocket);
System.out.println("paper");
setBackground(Color.white);
addMouseListener(this);
addMouseMotionListener(this);
color = Color.black;
setBorder(BorderFactory.createLineBorder(Color.black));
//save.setPreferredSize(new Dimension(100,20));
save.setMaximumSize(new Dimension(75,27));
erase.setMaximumSize(new Dimension(75,27));
}
public void paintComponent(Graphics g)
{
try
{
g.drawImage(image, 0, 0, this);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.black);
if(selected==("elipse"))
g2.drawOval(start.x, start.y,(end.x-start.x),(end.y-start.y));
else if(selected==("rect"))
g2.drawRect(start.x, start.y, (end.x-start.x),(end.y-start.y));
else if(selected==("line"))
g2.drawLine(start.x,start.y,end.x,end.y);
}
catch(Exception e)
{}
}
//Function to draw the shape on image
public void draw()
{
Graphics2D g2 = image.createGraphics();
g2.setPaint(color);
if(selected=="line")
g2.drawLine(start.x, start.y, end.x, end.y);
if(selected=="elipse")
g2.drawOval(start.x, start.y, (end.x-start.x),(end.y-start.y));
if(selected=="rect")
g2.drawRect(start.x, start.y, (end.x-start.x),(end.y-start.y));
repaint();
g2.dispose();
start=null;
}
//To add the point to the board which is broadcasted by the server
public synchronized void addPoint(Point ps,String varname,String shape,String event)
{
try
{
if(end==null)
end = new Point();
if(start==null)
start = new Point();
if(shape.equals("elipse"))
selected="elipse";
else if(shape.equals("line"))
selected="line";
else if(shape.equals("rect"))
selected="rect";
else if(shape.equals("erase"))
{
selected="erase";
erase();
}
if(end!=null && start!=null)
{
if(varname.equals("end"))
end=ps;
if(varname.equals("mp"))
mp=ps;
if(varname.equals("start"))
start=ps;
if(event.equals("drag"))
repaint();
else if(event.equals("release"))
draw();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//To set the size of the image
public void setWidth(int x,int y)
{
System.out.println("("+x+","+y+")");
w=x;
h=y;
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
g2.setPaint(Color.white);
g2.fillRect(0,0,w,h);
g2.dispose();
}
//Function which provides the erase functionality
public void erase()
{
Graphics2D pic=(Graphics2D) image.getGraphics();
pic.setPaint(Color.white);
pic.fillRect(start.x, start.y, 10, 10);
}
//Function to add buttons into the panel, calling this function returns a panel
public JPanel addButtons()
{
JPanel buttonpanel=new JPanel();
JPanel row1=new JPanel();
JPanel row2=new JPanel();
JPanel row3=new JPanel();
JPanel row4=new JPanel();
buttonpanel.setPreferredSize(new Dimension(80,80));
//buttonpanel.setMinimumSize(new Dimension(150,150));
row1.setLayout(new BoxLayout(row1,BoxLayout.X_AXIS));
row1.setPreferredSize(new Dimension(150,150));
row2.setLayout(new BoxLayout(row2,BoxLayout.X_AXIS));
row3.setLayout(new BoxLayout(row3,BoxLayout.X_AXIS));
row4.setLayout(new BoxLayout(row4,BoxLayout.X_AXIS));
buttonpanel.setLayout(new BoxLayout(buttonpanel,BoxLayout.Y_AXIS));
elipse.addActionListener(this);
rectangle.addActionListener(this);
line.addActionListener( this);
save.addActionListener( this);
erase.addActionListener( this);
buttonpanel.add(Box.createRigidArea(new Dimension(10,10)));
row1.add(elipse);
row1.add(Box.createRigidArea(new Dimension(5,0)));
row1.add(rectangle);
buttonpanel.add(row1);
buttonpanel.add(Box.createRigidArea(new Dimension(10,10)));
row2.add(line);
row2.add(Box.createRigidArea(new Dimension(5,0)));
row2.add(empty);
buttonpanel.add(row2);
buttonpanel.add(Box.createRigidArea(new Dimension(10,10)));
row3.add(save);
buttonpanel.add(row3);
buttonpanel.add(Box.createRigidArea(new Dimension(10,10)));
row4.add(erase);
buttonpanel.add(row4);
return buttonpanel;
}
//To save the image drawn
public void save()
{
try
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
JFileChooser fc = new JFileChooser();
fc.showSaveDialog(this);
encoder.encode(image);
byte[] jpgData = bos.toByteArray();
FileOutputStream fos = new FileOutputStream(fc.getSelectedFile()+".jpeg");
fos.write(jpgData);
fos.close();
//add replce confirmation here
}
catch (IOException e)
{
System.out.println(e);
}
}
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e)
{
if(selected=="line"||selected=="erase")
{
start=e.getPoint();
client.broadcast(start,"start", selected,"press");
}
else if(selected=="elipse"||selected=="rect")
{
mp = e.getPoint();
client.broadcast(mp,"mp", selected,"press");
}
}
public void mouseReleased(MouseEvent e)
{
if(start!=null)
{
if(selected=="line")
{
end=e.getPoint();
client.broadcast(end,"end", selected,"release");
}
else if(selected=="elipse"||selected=="rect")
{
end.x = Math.max(mp.x,e.getX());
end.y = Math.max(mp.y,e.getY());
client.broadcast(end,"end", selected,"release");
}
draw();
}
//start=null;
}
public void mouseDragged(MouseEvent e)
{
if(end==null)
end = new Point();
if(start==null)
start = new Point();
if(selected=="line")
{
end=e.getPoint();
client.broadcast(end,"end", selected,"drag");
}
else if(selected=="erase")
{
start=e.getPoint();
erase();
client.broadcast(start,"start", selected,"drag");
}
else if(selected=="elipse"||selected=="rect")
{
start.x = Math.min(mp.x,e.getX());
start.y = Math.min(mp.y,e.getY());
end.x = Math.max(mp.x,e.getX());
end.y = Math.max(mp.y,e.getY());
client.broadcast(start,"start", selected,"drag");
client.broadcast(end,"end", selected,"drag");
}
repaint();
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==elipse)
selected="elipse";
if(e.getSource()==line)
selected="line";
if(e.getSource()==rectangle)
selected="rect";
if(e.getSource()==save)
save();
if(e.getSource()==erase)
{
selected="erase";
erase();
}
}
}
class Button extends JButton
{
String name;
public Button(String name)
{
this.name=name;
Dimension buttonSize = new Dimension(35,35);
setMaximumSize(buttonSize);
}
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(1.2f));
if (name == "line") g.drawLine(5,5,30,30);
if (name == "elipse") g.drawOval(5,7,25,20);
if (name== "rect") g.drawRect(5,5,25,23);
}
}
Try maintaining a panel for each user, and layer them on top of each other. As long as the backgrounds are transparent, you should see them all fine.
Edit: To achieve the layers, you could try JLayeredPane.
I don't see any code there that handles requests arriving from the client. Assuming that is happening on a background thread, make sure you use SwingUtilities.invokeLater to make the changes on the EDT. Updating UI components from anywhere but the EDT will cause unpredictable behavior. See also Concurrency in Swing
Also, this sort of thing isn't going to work:
if (name == "line") g.drawLine(5,5,30,30);
In Java, the == operator performs an identity comparison. It evaluates true if name and "line" are the same object. It will evaluate false if they reference different objects, even if they both have the same value. To compare equality, you need to use the .equals() method.
Is there any trick to calling JFrame.setGlassPane(Component) more than once? In the code below, I first call it to create a red box in the glass pane. That works fine. Then, in a mouse click handler, I call it again to create a blue box in a new glass pane. This doesn't work. The original red glass pane disappears, but the blue glass pane does not appear. What am I doing wrong here?
public class GlassPaneProblem extends Component {
private BufferedImage img;
private JFrame f;
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public GlassPaneProblem() {
try {
img = ImageIO.read(new File("images/AppleCorps.JPG"));
} catch (IOException e) {
}
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
BlueGlassPane blueGlassPane = new BlueGlassPane();
setTheGlassPane(blueGlassPane);
}
});
}
public Dimension getPreferredSize() {
if (img == null) {
return new Dimension(100, 100);
} else {
return new Dimension(img.getWidth(null), img.getHeight(null));
}
}
public void run() {
f = new JFrame("Glass Pane Problem");
f.add(this);
f.pack();
RedGlassPane redGlassPane = new RedGlassPane();
setTheGlassPane(redGlassPane);
f.setVisible(true);
}
void setTheGlassPane(JComponent glassPane) {
f.setGlassPane(glassPane);
f.getGlassPane().setVisible(true);
}
public static void main(String[] args) {
GlassPaneProblem glassPaneProblem = new GlassPaneProblem();
glassPaneProblem.run();
}
}
class RedGlassPane extends JComponent {
protected void paintComponent(Graphics g) {
Rectangle clip = g.getClipBounds();
g.setColor(Color.RED);
g.fillRect(clip.x + clip.width / 3, clip.y + clip.height / 3,
clip.width / 3, clip.height / 3);
}
}
class BlueGlassPane extends JComponent {
protected void paintComponent(Graphics g) {
Rectangle clip = g.getClipBounds();
g.setColor(Color.BLUE);
g.fillRect(clip.x + clip.width / 3, clip.y + clip.height / 3,
clip.width / 3, clip.height / 3);
}
}
Calling repaint() like this does not fix the problem:
void setTheGlassPane(JComponent glassPane) {
f.setGlassPane(glassPane);
f.getGlassPane().setVisible(true);
f.repaint();
}
In setTheGlassPane(), add this as the first line:
f.getGlassPane().setVisible(false);