Wrap image to Jframe - java

I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
The objective with this solution is to convert a PDF to a image, identify a particular area using the visual mapper and then use PDFBox (PDFTextStripperbyArea) to extract against this area.
The co-ordinates being given by the below code is not extracting the required area's.
This is the code:
public class PDFVisualMapper extends JFrame {
BufferedImage image = null;
public static void main(String[] args) throws IOException {
new PDFVisualMapper();
}
public PDFVisualMapper() throws IOException {
this.setSize(1700, 2200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new PaintSurface(), BorderLayout.CENTER);
this.setVisible(true);
}
private class PaintSurface extends JComponent {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public PaintSurface() throws IOException {
image = ImageIO.read(new File("C:\\Users\\Rusty\\Desktop\\temp\\Test_PDF-1.png"));
if ( image != null ) {
Dimension size = new Dimension(image.getWidth(null), image.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
private void paintBackground(Graphics2D g2) {
g2.setPaint(Color.LIGHT_GRAY);
for (int i = 0; i < getSize().width; i += 10) {
Shape line = new Line2D.Float(i, 0, i, getSize().height);
g2.draw(line);
}
for (int i = 0; i < getSize().height; i += 10) {
Shape line = new Line2D.Float(0, i, getSize().width, i);
g2.draw(line);
}
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(g2);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.drawImage(image, null, 0, 0);
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
Can anybody help?

This might be simpler: using a JLabel within the contentpane, using FlowLayout:
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class WarpImage {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException{
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
BufferedImage image = ImageIO.read(url);
ImageIcon icon= new ImageIcon(image);
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel lbl= new JLabel();
lbl.setIcon(icon);
frame.add(lbl);
frame.pack();
//check size :
Rectangle bounds = lbl.getBounds();
System.out.println(bounds.getWidth() +"-"+ bounds.getHeight());
frame.setVisible(true);
}
}

I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
Then you paint the image yourself. Why? Because components like JLabel have their own internal layout mechanics which provide no way for you to determine the offset of the image within in, if the image is to large or to small for the component size.
Something like this, for example:
public class ImagePane extends JPanel {
private BufferedImage img;
public ImagePane(BufferedImage img) {
this.img = img;
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(0, 0) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(img, 0, 0, this);
g2.dispose();
}
}
}
This places the image in the top left corner of the component, so if it's resized for some reason, the image will always be in the top left position. To be frank, it wouldn't be hard to generate an offset to allow the image to be centred, this could then be used by decedents of the component to calculate the offset required to adjust their own output as needed

Related

Removing a rectangle with color on mouse release

I am developing a game and in some part of my game I want the rectangle to disappear on mouse release. I have placed 26 rectangles in an arrayList and remove the particular rectangle clicked as the mouse is released. So if I remove the fill methods, the rectangle disappears successfully but if the fill methods are there, it does not work anymore.
Here is my paint method:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Image img = Toolkit.getDefaultToolkit().getImage(Rectangles2.class.getResource("background.jpg"));
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle s : rectanglesList) {
g2.draw(s);
}
g2.setColor(bColor);
g2.fill(box1);
g2.fill(box2);
g2.fill(box3);
g2.fill(box4);
g2.fill(box5);
g2.fill(box6);
g2.fill(box7);
g2.fill(box8);
g2.fill(box9);
g2.fill(box10);
g2.fill(box11);
g2.fill(box12);
g2.fill(box25);
g2.setColor(wColor);
g2.fill(box13);
g2.fill(box14);
g2.fill(box15);
g2.fill(box16);
g2.fill(box17);
g2.fill(box18);
g2.fill(box19);
g2.fill(box20);
g2.fill(box21);
g2.fill(box22);
g2.fill(box23);
g2.fill(box24);
g2.fill(box26);
}
Here is how I did the removing of the rectangle (Just an excerpt):
if (box1.getBounds().contains(x, y)) {
pickedPanelNum = 0;
rectanglesList.remove(box1);
panelsPane.repaint();
}
Here are the values of the bColor and wColor:
Color bColor = Color.BLACK;
Color wColor = Color.WHITE;
NOTE:
The pickedPanelNum is just for assigning an int value and has no connection to the problem.
I think it is because when I repaint, the fill methods are still there. However I have no idea for an alternate way of painting the rectangles.
I hope my problem is stated clearly. If you have ideas how I could solve this, please tell me. Thank you!
UPDATE:
Here is a shorter, runnable version of my program. (Background image isn't included though):
import java.awt.*;
import java.awt.Color.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.geom.Rectangle2D;
public class Rec extends JComponent
{
public ArrayList<Rectangle> rectanglesList = new ArrayList<Rectangle>();
public int arrx[] = new int[120];
public int arry[] = new int[120];
JFrame frame = new JFrame();
public int xSize = 2000;
public int ySize = 1000;
public int x;
public int y;
public int pickedPanelNum = 0;
public String pickedPanelDash = "";
public String pickedPanelColor = "";
Color bColor = Color.BLACK;
Color wColor = Color.WHITE;
boolean removedPanel = false;
public void launchFrame()
{
Random rand = new Random();
for(int x = 0;x<120;x++)
{
arrx[x] = rand.nextInt(640);
arry[x] = rand.nextInt(590);
}
Rectangle box1 = new Rectangle(arrx[103],arry[59],80,90);
Rectangle box2 = new Rectangle(arrx[105],arry[3],80,90);
rectanglesList.add(box1);
rectanglesList.add(box2);
JPanel mainPanel = new JPanel();
JPanel panelsPane = new JPanel()
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Image img = Toolkit.getDefaultToolkit().getImage(Rectangles2.class.getResource("background.jpg"));
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle s : rectanglesList) {
g2.draw(s);
}
g2.setColor(bColor);
g2.fill(box1);
g2.setColor(wColor);
g2.fill(box2);
}
};
JPanel rightPane = new JPanel();
panelsPane.addMouseListener (new MouseAdapter ()
{
public void mousePressed(MouseEvent event)
{
x = event.getX();
y = event.getY();
}
public void mouseReleased(MouseEvent event)
{
if (box1.getBounds().contains(x, y)) {
pickedPanelNum = 0;
rectanglesList.remove(box1);
panelsPane.repaint();
}
if (box2.getBounds().contains(x, y)) {
pickedPanelNum = 1;
rectanglesList.remove(box2);
panelsPane.repaint();
}
}
});
panelsPane.addMouseMotionListener (new MouseAdapter ()
{
public void mouseDragged(MouseEvent event)
{
Rec obj = new Rec();
int dx = event.getX() - x;
int dy = event.getY() - y;
if (box1.getBounds().contains(x, y)) {
box1.x += dx;
box1.y += dy;
panelsPane.repaint();
}
if (box2.getBounds().contains(x, y)) {
box2.x += dx;
box2.y += dy;
panelsPane.repaint();
}
x += dx;
y += dy;
}
public void mouseReleased(MouseEvent event) {}
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
});
panelsPane.setPreferredSize(new Dimension (800, ySize-315));
rightPane.setPreferredSize(new Dimension (530, ySize-315));
mainPanel.setPreferredSize(new Dimension (xSize, ySize));
frame.setPreferredSize(new Dimension (xSize, ySize));
rightPane.setBackground(Color.gray);
mainPanel.add(panelsPane);
mainPanel.add(rightPane);
frame.add(mainPanel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
}
public static void main(String args[])
{
Rec obj = new Rec();
obj.launchFrame();
}
}
Even if you remove box1 from the List, there is nothing stopping it from getting filled in your paintComponent method, the for-loop is only drawing the outline of the rectangles within the list, but you code implicitly fills them anyway.
So, first, get rid of all the box{n} variables. Next change the paintComponent method...
public void paintComponent(Graphics g) {
super.paintComponent(g);
//Image img = Toolkit.getDefaultToolkit().getImage(Rectangles2.class.getResource("background.jpg"));
//g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle s : rectanglesList) {
g2.setColor(bColor);
g2.fill(s);
g2.setColor(wColor);
g2.draw(s);
}
}
So, this just uses the rectanglesList to first draw the rectangles and the fill them
Then, lets update the mouseReleased...
public void mouseReleased(MouseEvent event) {
// Because the rectangles are painted in order, the later
// rectangles are painted over the eailer ones, so, we reverse
// the list so we can check for the higher positioned
// rectangles
List<Rectangle> copy = new ArrayList<>(rectanglesList);
Collections.reverse(copy);
for (Rectangle r : copy) {
if (r.contains(event.getPoint())) {
rectanglesList.remove(r);
break;
}
}
event.getComponent().repaint();
}
Okay, this is little more funky, but basically, we reverse the list of rectangles (because those rectangles that appear later in the list are painted over those that appear before them) and checks to see if the mouse was clicked within any one of them. The moment we find a match, we break out of the loop and repaint the component which generated the event
And, because it's nice to see this stuff running, a complete example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Rec extends JComponent {
public ArrayList<Rectangle> rectanglesList = new ArrayList<Rectangle>();
public int arrx[] = new int[120];
public int arry[] = new int[120];
JFrame frame = new JFrame();
public int xSize = 2000;
public int ySize = 1000;
public int x;
public int y;
public int pickedPanelNum = 0;
public String pickedPanelDash = "";
public String pickedPanelColor = "";
Color bColor = Color.BLACK;
Color wColor = Color.WHITE;
boolean removedPanel = false;
public void launchFrame() {
Random rand = new Random();
for (int x = 0; x < 10; x++) {
arrx[x] = rand.nextInt(640);
arry[x] = rand.nextInt(590);
rectanglesList.add(new Rectangle(arrx[x], arry[x], 80, 90));
}
JPanel mainPanel = new JPanel();
JPanel panelsPane = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Image img = Toolkit.getDefaultToolkit().getImage(Rectangles2.class.getResource("background.jpg"));
// g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle s : rectanglesList) {
g2.setColor(bColor);
g2.fill(s);
g2.setColor(wColor);
g2.draw(s);
}
}
};
JPanel rightPane = new JPanel();
panelsPane.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
x = event.getX();
y = event.getY();
}
public void mouseReleased(MouseEvent event) {
// Because the rectangles are painted in order, the later
// rectangles are painted over the eailer ones, so, we reverse
// the list so we can check for the higher positioned
// rectangles
List<Rectangle> copy = new ArrayList<>(rectanglesList);
Collections.reverse(copy);
for (Rectangle r : copy) {
if (r.contains(event.getPoint())) {
rectanglesList.remove(r);
break;
}
}
event.getComponent().repaint();
}
});
panelsPane.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent event) {
}
public void mouseReleased(MouseEvent event) {
}
public void mouseClicked(MouseEvent event) {
}
public void mouseEntered(MouseEvent event) {
}
public void mouseExited(MouseEvent event) {
}
});
panelsPane.setPreferredSize(new Dimension(800, ySize - 315));
rightPane.setPreferredSize(new Dimension(530, ySize - 315));
mainPanel.setPreferredSize(new Dimension(xSize, ySize));
frame.setPreferredSize(new Dimension(xSize, ySize));
rightPane.setBackground(Color.gray);
mainPanel.add(panelsPane);
mainPanel.add(rightPane);
frame.add(mainPanel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
}
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();
}
Rec obj = new Rec();
obj.launchFrame();
}
});
}
}

Saving a JPanel as an Image (object) and drawing it back onto a JPanel

I've had a look around and tried using other queries, but I just can't seem to get this to work.
I am trying to retain an image from a JPanel drawn via the g.draw/fill methods.
I've attempted to save the drawing in a buffered image, but when I display it in a messageDialog all I get is the background and none of the drawings
These two methods are the important code (from the DrawingPanel class):
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
They get called here:
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
Here is the whole program, it should run.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TestClass extends JFrame implements ActionListener {
DrawingPanel dp;
public TestClass() {
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel top = new JPanel();
JButton load = new JButton("Load Image");
load.addActionListener(this);
top.add(load);
dp = new DrawingPanel();
dp.setBackground(Color.CYAN);
add(top, BorderLayout.NORTH);
add(dp, BorderLayout.CENTER);
setVisible(true);
}
public static void main(String[] args) {
new TestClass();
}
#Override
public void actionPerformed(ActionEvent ae) {
BufferedImage bi = dp.getScreenShot();
dp.loadDrawing(bi);
}
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
#Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
Graphics g = getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
BufferedImage image = new BufferedImage(this.getWidth(),
this.getHeight(), BufferedImage.TYPE_INT_RGB);
// call the Panels's paint method, using
// the Graphics object of the image.
this.paint(image.getGraphics());
return image;
}
//unused abstract method
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseMoved(MouseEvent me) {
}
}
}
I need to be able to store the graphics from the panel and retrieve it.
Help would be heavily appreciated.
Every attempt to draw something into the Graphics object that was obtained from a Component by calling getGraphics will fail sooner or later. This Graphics object merely serves as a "path" to the actual screen (that is only valid while the component is actually painted on the screen). It is not a "buffer", and it does not "store" anything that was drawn.
If you want to create a simple painting program, you should draw to a BufferedImage. And when the DrawingPanel is to be painted, you only paint this BufferedImage. The additional advantage here is that when you want to make a screenshot, you basically just have to return a copy of this BufferedImage.
I sketeched the basic approach in your DrawingPanel class, with some in-lined comments. It could be cleaned up and beautified, and there are some aspects to consider (e.g. what should happen when the DrawingPanel is resized?), but it shows how it should work in general:
private class DrawingPanel extends JPanel implements
MouseListener, MouseMotionListener {
// The image that will store what was drawn. In the
// mouseDragged method, the painting operations will
// go directly to this image. When this panel is
// painted, then ONLY this image will be painted.
private BufferedImage bufferedImage;
private int xPos, yPos;//mouse positions
private DrawingPanel() {
addMouseListener(this);
addMouseMotionListener(this);
}
// Make sure that the "bufferedImage" is non-null
// and has the same size as this panel
private void validateImage()
{
if (bufferedImage == null)
{
bufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.dispose();
}
if (bufferedImage.getWidth() != getWidth() ||
bufferedImage.getHeight() != getHeight())
{
BufferedImage newBufferedImage = new BufferedImage(
getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics g = newBufferedImage.getGraphics();
g.setColor(getBackground());
g.fillRect(0,0,getWidth(),getHeight());
g.drawImage(bufferedImage, 0,0,null);
g.dispose();
bufferedImage = newBufferedImage;
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
validateImage();
// Paint the bufferedImage which stores
// what was drawn until now
g.drawImage(bufferedImage, 0, 0, null);
}
#Override
public void mousePressed(MouseEvent me) {
xPos = me.getX();
yPos = me.getY();
}
#Override
public void mouseDragged(MouseEvent me) {
int x = me.getX(), y = me.getY();
validateImage();
// Paint directly into the bufferedImage here
Graphics g = bufferedImage.getGraphics();
g.setColor(Color.BLACK);
g.drawOval(xPos, yPos, 30, 30);
repaint();
xPos = x;
yPos = y;
}
public void loadDrawing(BufferedImage bi) {
//opens a message dialog and displays the image parameter
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
}
public BufferedImage getScreenShot() {
// This basically returns a "copy" of the
// bufferedImage that stores what was drawn
BufferedImage image = new BufferedImage(
getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.drawImage(bufferedImage, 0, 0, null);
g.dispose();
return image;
}
//unused abstract method
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseMoved(MouseEvent me) {
}
}
Your getting your Graphics object by calling getGraphics() on a component, and images drawn with this will not persist. Why not instead draw to a BufferedImage with its Graphics object, and then simply save that BufferedImage. This would simplify things greatly, and your program would work.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestClass2 extends JPanel {
private DrawingPanel drawingPanel = new DrawingPanel();
public TestClass2() {
JPanel northPanel = new JPanel();
northPanel.add(new JButton(new GetImageAction("Get Image")));
northPanel.add(new JButton(new ClearImageAction("Clear Image")));
setLayout(new BorderLayout(5, 5));
add(drawingPanel, BorderLayout.CENTER);
add(northPanel, BorderLayout.NORTH);
}
private class GetImageAction extends AbstractAction {
public GetImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_G);
}
#Override
public void actionPerformed(ActionEvent evt) {
BufferedImage img = drawingPanel.getMainImage();
ImageIcon icon = new ImageIcon(img);
JOptionPane.showMessageDialog(TestClass2.this, icon);
}
}
private class ClearImageAction extends AbstractAction {
public ClearImageAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
#Override
public void actionPerformed(ActionEvent evt) {
drawingPanel.clearImage();
drawingPanel.repaint();
}
}
private static void createAndShowGui() {
TestClass2 mainPanel = new TestClass2();
JFrame frame = new JFrame("TestClass2");
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();
}
});
}
}
class DrawingPanel extends JPanel {
public static final int BI_WIDTH = 400;
public static final int BI_HEIGHT = BI_WIDTH;
private static final Color BACKGROUND = Color.CYAN;
public static final Color DRAW_COLOR = Color.black;
public static final int OVAL_WIDTH = 30;
private BufferedImage mainImage;
public DrawingPanel() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
clearImage();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mainImage != null) {
g.drawImage(mainImage, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
public BufferedImage getMainImage() {
return mainImage;
}
public void clearImage() {
mainImage = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = mainImage.getGraphics();
g.setColor(BACKGROUND);
g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g.dispose();
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent mEvt) {
draw(mEvt);
}
#Override
public void mouseDragged(MouseEvent mEvt) {
draw(mEvt);
}
private void draw(MouseEvent mEvt) {
Graphics2D g2 = mainImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(DRAW_COLOR);
g2.drawOval(mEvt.getX() - OVAL_WIDTH / 2, mEvt.getY() - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
g2.dispose();
repaint();
}
}
}

Image Pan and Zooming

I want to display an image to zoom in and out and can be shifted. I have the script below, but it can not be shifted. how to fix it.
the code :
package dispertasih;
import static dispertasih.PanPanel.startX;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class PadAndZoom implements ChangeListener {
BufferedImage image;
PanPanel label;
public void stateChanged(ChangeEvent e) {
int value = ((JSlider)e.getSource()).getValue();
double scale = value/200.0;
BufferedImage scaled = getScaledImage(scale);
label = new PanPanel(scaled);
label.revalidate(); // signal scrollpane
}
private BufferedImage getScaledImage(double scale) {
int w = (int)(scale*image.getWidth());
int h = (int)(scale*image.getHeight());
BufferedImage bi = new BufferedImage(w, h, image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
g2.drawRenderedImage(image, at);
g2.dispose();
return bi;
}
private PanPanel getContent() {
createAnImage();
label = new PanPanel(image);
//label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
private void createAnImage() {
int w = 500;
int h = 500;
int type = BufferedImage.TYPE_INT_RGB; // many options
try {
image = ImageIO.read(PadAndZoom.class.getResource("/tampilan/background5.jpg"));
} catch (IOException ex) {
Logger.getLogger(PadAndZoom.class.getName()).log(Level.SEVERE, null, ex);
}
}
private JSlider getControl() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 50, 200, 50);
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(this);
return slider;
}
public static void main(String[] args) {
PadAndZoom app = new PadAndZoom();
JFrame f = new JFrame();
JButton b = new JButton();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(app.getContent()));
//f.getContentPane().add(new JButton("tessss"));
f.getContentPane().add(app.getControl(), "Last");
f.setSize(400, 400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class PanPanelX extends JPanel {
private int x, y;
private int width = 800, height = 800;
BufferedImage img;
private final static RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
private final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
private final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
static int startX, startY;
public PanPanelX(BufferedImage img) {
x = 20;
y = 20;
this.img = img;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
startX = me.getX();
startY = me.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
if (me.getX() < startX) {//moving image to right
x -= 2;
} else if (me.getX() > startX) {//moving image to left
x += 2;
}
if (me.getY() < startY) {//moving image up
y -= 2;
} else if (me.getY() > startY) {//moving image to down
y += 2;
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
//turn on some nice effects
applyRenderHints(g2d);
g2d.drawImage(img, x, y, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public static void applyRenderHints(Graphics2D g2d) {
g2d.setRenderingHints(textRenderHints);
g2d.setRenderingHints(imageRenderHints);
g2d.setRenderingHints(renderHints);
}
}
i think on :
public void stateChanged(ChangeEvent e) {
int value = ((JSlider)e.getSource()).getValue();
double scale = value/200.0;
BufferedImage scaled = getScaledImage(scale);
label = new PanPanel(scaled);
label.revalidate(); // signal scrollpane
}
there are mistakes, but I've stuck fixing it....
thank you ...
The problem is, the reference of the image that is displayed on the screen is not the same as the image you are creating when you resize it...
You create PanPanel by using...
BufferedImage scaled = getScaledImage(scale);
label = new PanPanel(scaled);
getScaledImage creates a new image each time it is called, based on the original image.
BufferedImage bi = new BufferedImage(w, h, image.getType());
This means, that the image in PadAndZoom is not the same as the one in PanPanel, so any changes you make to image or any new scaled instances will never be painted because PanPanel knows nothing about them...
Now, in stateChanged, instead of updating the instance of PanPanel that you already have, you create a new instance of it...and that's it...it's never added to any displayable component, so it will never appear on the screen.
Instead, in your PanPanel, you need to supply some way for the stateChanged method to pass the scaled instance of the image to it...
public void setImage(BufferedImage img) {
this.img = img;
revalidate();
repaint();
}
Then in your stateChanged method you can do...
int value = ((JSlider) e.getSource()).getValue();
double scale = value / 200.0;
BufferedImage scaled = getScaledImage(scale);
label.setImage(scaled);

How to add imagepanel in jpanel inside Jframe?

I'm trying to add an imagepanel which extends JPanel to another JPanel. Which is not working well for me. The paint function of image panel don't get invoked inside Jpanel but works fine in JFrame. Any ideas or help will be appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
class ImagePanel extends JPanel
{
int g_h=10,g_w=10;
int width=50,height=50;
int cornerradius;
Image castle;
Dimension size;
protected int x1,y1;
Color c1=new Color(255, 0, 0);
Rectangle rec;
boolean b=false;
boolean imboo=false;
boolean roundb= false;
Graphics g= this.getGraphics();
protected int strokeSize = 1;
protected Color shadowColor = Color.BLACK;
boolean shadowed = false;
public ImagePanel()
{
//super();
setOpaque(false);
setLayout(null);
System.out.println("it executed");
}
public ImagePanel(int x, int y)
{
setSize(x, y);
}
public void setSize(int x,int y){
width=x;
height=y;
}
public int getheight(){
return height;
}
public int getwidth(){
return width;
}
public void setImagePanelBounds(
int x, int y, int width, int height){
x1=x;
y1=y;
this.width= width;
this.height= height;
System.out.println("6it executed");
}
public void setroundcorners(boolean b, int i){
roundb=b;
cornerradius=i;
System.out.println("5it executed");
}
public void setImage(String s){
imboo=true;
size = new Dimension();
castle = new ImageIcon(s).getImage();
size.width = castle.getWidth(null);
size.height = castle.getHeight(null);
setPreferredSize(size);
System.out.println("4it executed");
}
public void paint(Graphics gh){
System.out.println("it executed p");
{int x=this.getWidth();
int j=20,a=20;
Graphics2D g2= (Graphics2D)gh.create();
{
g2.setColor(Color.WHITE);
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.SrcAtop);
rec= new Rectangle(x1, y1, width, height);
//Start of If-else
if(roundb){
g2.setClip(new RoundRectangle2D.Float(
(int)rec.getX(),(int)rec.getY(),
(int)rec.getWidth(),(int)rec.getHeight(),
cornerradius, cornerradius));
System.out.println("it executed");
}
// End of If-Else
// Image condition Starts
if (imboo){
g2.drawImage(castle, (int)rec.getX(),
(int)rec.getY(), (int)rec.getWidth(),
(int)rec.getHeight(), null);
//g.drawImage(castle, (int)rec.getX(),(int)rec.getY(), null);
}
// Image condition Ends
g2.setColor(Color.BLUE);
}
}
}
public static void main(String[]args)
{
ImagePanel t1=new ImagePanel();
JPanel jp1= new JPanel();
jp1.add(t1);
jp1.setLayout(null);
jp1.setBounds(0, 0, 600, 600);
JFrame jf1= new JFrame("Testing");
t1.setImage("icons/1.png");
//t1.setImage("1.jpg");
t1.setLayout(null);
t1.setroundcorners(true, 10);
//t1.setShadow(true);
t1.add(new JLabel("niak"));
//t1.setShadowDimensions(18, 18, 305, 305, 12);
t1.setImagePanelBounds(20, 20, 100, 100);
// jf1.add(t1);
jf1.setSize(600, 600);
jf1.setDefaultCloseOperation(jf1.EXIT_ON_CLOSE);
jf1.setVisible(true);
//jf1.revalidate();
jf1.setLayout(null);
}
}
Let's start with...
Don't use getGraphics. This is not how to perform custom painting. getGraphics may return null and is, at best, a snapshot, which will be discard when the next paint cycle occurs.
JPanel already has getWidth, getHeight and setSize methods, you should never have a need to overridden them. Instead, you should override getPreferredSize and return a size hint back that the parent layout manager can use.
If you create a Graphics context, you should dispose of it. In your paint method, you use gh.create, this is consuming resources and under some systems, until the Graphics context is disposed, it may not actually paint anything.
Don't override paint, instead use paintComponent
DO NOT modify the clip rectangle. Seriously, this is going to cause you more issues then you can imagine.
Don't use null layout managers without EXTREMELY good reason.
JPanel has a setBounds method, while, under normal circumstances, you shouldn't need to use it, since you've thrown away the layout manager, you should use it.
Basically, you've discard all the inner workings of the JPanel that enable the paint system to know that it should actually paint your panel
Updated with example
As an example...
Instead of using the clip, I use a masking technique, and mask the shape I want over the source image. I also buffer the result, which should make it more memory conservative as well as render faster
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class ImagePaneExample {
public static void main(String[] args) {
new ImagePaneExample();
}
public ImagePaneExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
BufferedImage img = ImageIO.read(new File("C:\\hold\\thumbnails\\2005-09-29-3957.jpeg"));
ImagePane imgPane = new ImagePane();
imgPane.setImage(img);
imgPane.setRounded(true);
imgPane.setBorder(new EmptyBorder(20, 20, 20, 20));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(imgPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
public class ImagePane extends JPanel {
private BufferedImage img;
private BufferedImage renderImg;
private boolean rounded;
public ImagePane() {
}
public void setRounded(boolean value) {
if (value != rounded) {
rounded = value;
renderImg = null;
firePropertyChange("rounded", !rounded, rounded);
repaint();
}
}
public boolean isRounded() {
return rounded;
}
public void setImage(BufferedImage value) {
if (value != img) {
BufferedImage old = img;
img = value;
renderImg = null;
firePropertyChange("image", old, img);
repaint();
}
}
public BufferedImage getImage() {
return img;
}
#Override
public Dimension getPreferredSize() {
Dimension size = img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
Insets insets = getInsets();
size.width += (insets.left + insets.right);
size.height += (insets.top + insets.bottom);
return size;
}
protected void applyQualityRenderHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
protected BufferedImage getImageToRender() {
if (renderImg == null) {
BufferedImage source = getImage();
if (source != null) {
if (isRounded()) {
BufferedImage mask = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, mask.getWidth(), mask.getHeight());
g2d.setBackground(new Color(255, 255, 255, 255));
g2d.fillRoundRect(0, 0, mask.getWidth(), mask.getHeight(), 40, 40);
g2d.dispose();
BufferedImage comp = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = comp.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, source.getWidth(), source.getHeight());
g2d.drawImage(source, 0, 0, this);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
g2d.drawImage(mask, 0, 0, this);
g2d.dispose();
renderImg = comp;
} else {
renderImg = source;
}
}
}
return renderImg;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = getImageToRender();
System.out.println(img);
if (img != null) {
Insets insets = getInsets();
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int x = ((width - img.getWidth()) / 2);
int y = ((height - img.getHeight()) / 2);
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
I'd recommend some more reading through Creating a UI with Swing, in particular the section on layout managers, as well as Performing Custom Painting and Painting in AWT and Swing
All you have to do is to set the Layout of your panel jp1 to BorderLayout and add the image panel t1 to BorderLayout.CENTER, like this:
JPanel jp1= new JPanel(new BorderLayout());
jp1.add(t1, BorderLayout.CENTER);

Java Swing - Valid approach for dragging rectangles onto a JPanel?

I have some code to draw rectangles. It's used to draw rectangles on a JPanel, to mark boundaries of widgets. Here the code first, after that I'll explain my problem cq. question.
First off, I have a class (WidgetDrawingPanel) which extends JPanel.
public WidgetDrawingPanel(int width, int height) {
/*To make things visible at least*/
widgets.add(new Widget(10,10,100,100, WidgetType.TextField));
widgets.add(new Widget(50,50,100,200, WidgetType.TextField));
this.width = width;
this.height = height;
this.setBackground(Color.BLUE);
addListener(); //adds both MouseMotionListener and MouseListener
}
Below you'll see me reference ch a lot. This is a CoordinateHolder, which holds start and current coordinates of my mouse movement.
private void addListener() {
this.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent arg0) {
ch.currentX = arg0.getX();
ch.currentY = arg0.getY();
System.out.println("dragging " + ch.currentX + ","+ch.currentY);
WidgetDrawingPanel.this.repaint();
}
});
this.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent event) {
ch.endX = event.getX();
ch.endY = event.getY();
try {
checkCoords();
} catch (OutsidePanelException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "drawn Outside Panel");
}
}
#Override
public void mousePressed(MouseEvent event) {
ch = new CoordinateHolder(event.getX(), event.getY());
}
});
}
and, finally, the paintComponent(Grapics) method. There's loop through Widgets, which are actually just already drawn Rects (x, y, w, h attributes), but which a little more information, which is not useful in the drawing part of the application. Everytime you release the mouse, the CoordinateHolder is converted into a Widget, and added to widgets.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("Paint");
g.setColor(Color.BLUE);
g.fillRect(0, 0, width, height); //making the whole panel blue
g.setColor(Color.RED);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(new BasicStroke(3));
for (Widget w : widgets) {
g.drawRect(w.getX(), w.getY(), w.getW(), w.getH());
}
if (ch != null)
g.drawRect(ch.startX, ch.startY, ch.currentX - ch.startX, ch.currentY - ch.startY);
}
This code is working, but I suspect this is highly inefficient and inperformant, as above code continually refreshes the JPanel on mouse drag, which is, say, once every 10ms? I suppose it'll get slow really soon, especially when the user creates a heck of a lot rectangles (which are also continally redrawn, as seen in painComponent(Graphics)).
Question cq. Problem
Is there a better, less resource consuming method, where the user can drag rectangles smoothly?
I read an answer to this Drag rectangle on JFrame in Java, but the author of that answer seems to do it the same as me. But again, that's way inperformant, right? Or should computers be easily able to redraw the component continually, and is this actually a valid approach?
To show lots of non-changing background shapes, draw them to a BufferedImage and then show that BufferedImage in the paintComponent(...) method. So while a shape is being drawn, draw it in paintComponent(...) but once the shape is done being drawn, perhaps on mouseRelease, then draw it in the background BufferedImage.
Note that what will slow your current drawing code the most may be your debugging SOP statements, but I assume that these will be removed from the finished code.
For example:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class DrawingPanel extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
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;
public DrawingPanel() {
backgroundImg = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
Graphics g = backgroundImg.getGraphics();
g.setColor(Color.blue);
g.fillRect(0, 0, PREF_W, PREF_H);
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(PREF_W, PREF_H);
}
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 = new DrawingPanel();
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();
}
});
}
}

Categories