Problems making a paint program - java

I'm kinda new to java and have been trying to make a simple paint program, I have gotten everything to work except the color of the paint brush. Rigth now I set the color to blue but I want to make the color of the paint brush the same color as the color selected by the color slider.
Here's the code I got so far
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class Paint extends JFrame implements ChangeListener{
PaintPanel color;
PaintPanel2 paint;
JSlider red;
JSlider green;
JSlider blue;
public Paint(){
super("Paint");
setSize(300,290);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
color = new PaintPanel();
paint = new PaintPanel2();
red = new JSlider(0,255,255);
green = new JSlider(0,255,0);
blue = new JSlider(0,255,0);
red.setMajorTickSpacing(50);
red.setMinorTickSpacing(10);
red.setPaintTicks(true);
red.setPaintLabels(true);
red.addChangeListener(this);
green.setMajorTickSpacing(50);
green.setMinorTickSpacing(10);
green.setPaintTicks(true);
green.setPaintLabels(true);
green.addChangeListener(this);
blue.setMajorTickSpacing(50);
blue.setMinorTickSpacing(10);
blue.setPaintTicks(true);
blue.setPaintLabels(true);
blue.addChangeListener(this);
JLabel redLabel = new JLabel("Red: ");
JLabel greenLabel = new JLabel("Green: ");
JLabel blueLabel = new JLabel("Blue: ");
GridLayout grid = new GridLayout(5,1);
FlowLayout flow = new FlowLayout(FlowLayout.RIGHT);
setLayout(grid);
JPanel redPanel = new JPanel();
redPanel.setLayout(flow);
redPanel.add(redLabel);
redPanel.add(red);
add(redPanel);
JPanel greenPanel = new JPanel();
greenPanel.setLayout(flow);
greenPanel.add(greenLabel);
greenPanel.add(green);
add(greenPanel);
JPanel bluePanel = new JPanel();
bluePanel.setLayout(flow);
bluePanel.add(blueLabel);
bluePanel.add(blue);
add(bluePanel);
add(color);
add(paint);
setVisible(true);
}
public void stateChanged(ChangeEvent e){
JSlider source = (JSlider) e.getSource();
if(source.getValueIsAdjusting() != true){
Color mainColor = new Color(red.getValue(),
green.getValue(),
blue.getValue());
color.changeColor(mainColor);
color.repaint();
}
}
public static void main(String[] args){
Paint p = new Paint();
}
}
class PaintPanel extends JPanel{
Color background;
public PaintPanel(){
background = Color.red;
}
public void paintComponent(Graphics comp){
Graphics2D comp2D = (Graphics2D) comp;
comp2D.setColor(background);
comp2D.fillRect(0,0,getSize().width,getSize().height);
}
void changeColor(Color newBackground){
background = newBackground;
}
}
class PaintPanel2 extends JPanel{
Image image;
Graphics2D comp2D;
int currentX, currentY, oldX, oldY;
PaintPanel color;
public PaintPanel2(){
color = new PaintPanel();
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
currentX = e.getX();
currentY = e.getY();
if(comp2D != null)
comp2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
});
}
public void paintComponent(Graphics comp){
if(image == null){
image = createImage(getSize().width, getSize().height);
comp2D = (Graphics2D)image.getGraphics();
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
comp2D.setPaint(Color.white);
comp2D.fillRect(0, 0, getSize().width, getSize().height);
comp2D.setPaint(Color.blue);
repaint();
}
comp.drawImage(image, 0, 0, null);
}
}

The problem was that you weren't setting the chosen color in PaintPanel2. I changed the stateChanged method and the PaintPanel2 as follows, and now it works as I assume you intended:
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (source.getValueIsAdjusting() != true) {
Color mainColor = new Color(red.getValue(),
green.getValue(),
blue.getValue());
color.changeColor(mainColor);
paint.setPaintColor(mainColor);
color.repaint();
}
}
class PaintPanel2 extends JPanel {
Image image;
Graphics2D comp2D;
int currentX, currentY, oldX, oldY;
public PaintPanel2() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
if (comp2D != null) {
comp2D.drawLine(oldX, oldY, currentX, currentY);
}
repaint();
oldX = currentX;
oldY = currentY;
}
});
}
public void paintComponent(Graphics comp) {
if (image == null) {
image = createImage(getSize().width, getSize().height);
comp2D = (Graphics2D) image.getGraphics();
comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
comp2D.setPaint(Color.white);
comp2D.fillRect(0, 0, getSize().width, getSize().height);
comp2D.setPaint(Color.blue);
repaint();
}
comp.drawImage(image, 0, 0, null);
}
public void setPaintColor(Color color) {
comp2D.setColor(color);
}
}

Related

Implement in JAVA a rectangle shape feature like in Paint

I want to implement a Rectangle shape feature exactly as in Paint in JAVA. I have built a program as following. I have built a class MyPaint where buttons and frame are defined. I have built another class inside the same program PadDraw, where a drawing pad is created where I can draw with pencil like in Paint. Then I have another class outside the program DrawRect where the rectangle shape feature is created.
I want to know if there is a way to integrate the rectangle in a way that if I click a button "Rectangle", the way of drawing should change and instead of drawing with pencil, I should draw rectangle shapes exactly like in Paint when the rectangle shape is pressed.
The piece of code for PadDraw class is as following:
class PadDraw extends JComponent {
private Image image;
private Graphics2D graphics2D;
private int currentX , currentY , oldX , oldY ;
public PadDraw(){
setDoubleBuffered(false);
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
currentX = e.getX();
currentY = e.getY();
if(graphics2D != null)
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
});
}
public void paintComponent(Graphics g){
if(image == null){
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 5, 5, null);
}
While the piece of code of DrawRect class that I want to integrate in the program where MyPaint and PadDraw class are located is as following:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawRect extends JPanel {
int x, y, x2, y2;
public static void main(String[] args) {
JFrame f = new JFrame("Draw Box Mouse 2");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new DrawRect());
f.setSize(300, 300);
f.setVisible(true);
}
DrawRect() {
x = y = x2 = y2 = 0; //
MyMouseListener listener = new MyMouseListener();
addMouseListener(listener);
addMouseMotionListener(listener);
}
public void setStartPoint(int x, int y) {
this.x = x;
this.y = y;
}
public void setEndPoint(int x, int y) {
x2 = (x);
y2 = (y);
}
public void drawPerfectRect(Graphics g, int x, int y, int x2, int y2) {
int px = Math.min(x,x2);
int py = Math.min(y,y2);
int pw=Math.abs(x-x2);
int ph=Math.abs(y-y2);
g.drawRect(px, py, pw, ph);
}
class MyMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
setStartPoint(e.getX(), e.getY());
}
public void mouseDragged(MouseEvent e) {
setEndPoint(e.getX(), e.getY());
repaint();
}
public void mouseReleased(MouseEvent e) {
setEndPoint(e.getX(), e.getY());
repaint();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
drawPerfectRect(g, x, y, x2, y2);
}
}

Use Buttons and mouse to control draw-board

I am doing a GUI that is supposed to work like a Paint application. My current problem is adding proper functionality to my draw line and draw rectangle buttons. They currently don't work as I expected them to work. Help will be greatly appreciated.
I searched many code snippets on learning how to draw shapes but none of them show how to make them work based on if they are activated based on the buttons, and how to alternate from drawing a line to drawing rectangles.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class paintGUI extends JComponent {
// Image in which we're going to draw
private Image image;
// Graphics2D object ==> used to draw on
private Graphics2D g2;
// Mouse coordinates
private int currentX, currentY, oldX, oldY;
public paintGUI() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw line if g2 context not null
//g2.drawLine(oldX, oldY, currentX, currentY);
//Need to implement these to their button
//g2.drawRect(oldX, oldY, currentX, currentY);
//g2.fillRect(oldX, oldY, currentX, currentY);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
}
#Override
protected void paintComponent(Graphics g) {
if (image == null) {
// image to draw null ==> we create
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
// clear draw area
clear();
}
g.drawImage(image, 0, 0, null);
}
// now we create exposed methods
public void clear() {
g2.setPaint(Color.white);
// draw white on entire draw area to clear
g2.fillRect(0, 0, getSize().width, getSize().height);
g2.setPaint(Color.black);
repaint();
}
public void thin() {
g2.setStroke(new BasicStroke(3));
}
public void thick() {
g2.setStroke(new BasicStroke(10));
}
public void red() {
// apply red color on g2 context
g2.setPaint(Color.red);
}
public void black() {
g2.setPaint(Color.black);
}
public void magenta() {
g2.setPaint(Color.magenta);
}
public void drawLine() {
g2.drawLine(oldX, oldY, currentX, currentY);
}
public void drawRectangle() {
g2.drawRect(oldX, oldY, currentX, currentY);
g2.fillRect(oldX, oldY, currentX, currentY);
}
}
class GUIPaint {
JButton clearBtn, blackBtn, redBtn, magentaBtn, filledRectangleBtn, lineBtn, thinBtn, thickBtn;
paintGUI paintGUI;
ActionListener actionListener = e -> {
if (e.getSource() == clearBtn) {
paintGUI.clear();
} else if (e.getSource() == thinBtn) {
paintGUI.thin();
} else if (e.getSource() == thickBtn) {
paintGUI.thick();
} else if (e.getSource() == blackBtn) {
paintGUI.black();
} else if (e.getSource() == redBtn) {
paintGUI.red();
} else if (e.getSource() == magentaBtn) {
paintGUI.magenta();
} else if (e.getSource() == filledRectangleBtn) {
paintGUI.drawLine();
} else if (e.getSource() == lineBtn) {
paintGUI.drawRectangle();
}
};
public static void main(String[] args) {
new GUIPaint().show();
}
public void show() {
// create main frame
JFrame frame = new JFrame("Swing Paint");
Container content = frame.getContentPane();
// set layout on content pane
content.setLayout(new BorderLayout());
// create draw area
paintGUI = new paintGUI();
// add to content pane
content.add(paintGUI, BorderLayout.CENTER);
// create controls to apply colors and call clear feature
JPanel controls = new JPanel();
clearBtn = new JButton("Clear");
clearBtn.addActionListener(actionListener);
blackBtn = new JButton("Black");
blackBtn.addActionListener(actionListener);
redBtn = new JButton("Red");
redBtn.addActionListener(actionListener);
magentaBtn = new JButton("Magenta");
magentaBtn.addActionListener(actionListener);
lineBtn = new JButton("Line");
lineBtn.addActionListener(actionListener);
filledRectangleBtn = new JButton("Filled Rectangle");
filledRectangleBtn.addActionListener(actionListener);
thickBtn = new JButton("Thick Line");
thickBtn.addActionListener(actionListener);
thinBtn = new JButton("Thin Line");
thinBtn.addActionListener(actionListener);
controls.add(lineBtn);
controls.add(filledRectangleBtn);
controls.add(thinBtn);
controls.add(thickBtn);
controls.add(blackBtn);
controls.add(redBtn);
controls.add(magentaBtn);
controls.add(clearBtn);
// add to content pane
content.add(controls, BorderLayout.NORTH);
frame.setSize(800, 800);
// can close frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// show the swing paint result
frame.setVisible(true);
}
}
I need the program to properly respond if I click the line button to be able to draw a line or if the rectangle button is pressed than draw rectangle.
The basic idea is to let the controls (buttons, mouse) change the attributes (color, shape, stroke, coordinates) and invoke repaint.
paintComponent uses those attributes to draw the right shape.
Note the commented modifications of your code.
The code is one-file mre: the entire code can be copy pasted into GUIPaint.java and run:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import swing_tests.PaintGUI.SHAPE;
public class GUIPaint {
private PaintGUI paintGUI;
public void showGui() {
JFrame frame = new JFrame("Swing Paint");
Container content = frame.getContentPane();
content.setLayout(new BorderLayout());
paintGUI = new PaintGUI();
content.add(paintGUI, BorderLayout.CENTER);
// create controls to apply colors and call clear feature
JPanel controls = new JPanel();
//todo: reduce duplicate code by having a method that constructs
//and adds a button
//todo: use button groups where only one button can be selected
JButton clearBtn = new JButton("Clear");
JButton blackBtn = new JButton("Black");
JButton redBtn = new JButton("Red");
JButton magentaBtn = new JButton("Magenta");
JButton lineBtn = new JButton("Line");
JButton filledRectangleBtn = new JButton("Filled Rectangle");
JButton thickBtn = new JButton("Thick Line");
JButton thinBtn = new JButton("Thin Line");
//todo: register an Action listner to each button by using lambda
//for example clearBtn.addActionListener(e-> paintGUI.clear());
ActionListener actionListener = e -> {
if (e.getSource() == clearBtn) {
paintGUI.clear();
}else if (e.getSource() == thinBtn) {
paintGUI.thin();
} else if (e.getSource() == thickBtn) {
paintGUI.thick();
} else if (e.getSource() == blackBtn) {
paintGUI.black();
} else if (e.getSource() == redBtn) {
paintGUI.red();
} else if (e.getSource() == magentaBtn) {
paintGUI.magenta();
} else if (e.getSource() == filledRectangleBtn) {
paintGUI.setShape(SHAPE.RECTANGLE);
} else if (e.getSource() == lineBtn) {
paintGUI.setShape(SHAPE.LINE);
}
};
clearBtn.addActionListener(actionListener);
blackBtn.addActionListener(actionListener);
redBtn.addActionListener(actionListener);
magentaBtn.addActionListener(actionListener);
lineBtn.addActionListener(actionListener);
filledRectangleBtn.addActionListener(actionListener);
thickBtn.addActionListener(actionListener);
thinBtn.addActionListener(actionListener);
controls.add(lineBtn);
controls.add(filledRectangleBtn);
controls.add(thinBtn);
controls.add(thickBtn);
controls.add(blackBtn);
controls.add(redBtn);
controls.add(magentaBtn);
controls.add(clearBtn);
content.add(controls, BorderLayout.NORTH);
frame.setSize(800, 800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(()-> new GUIPaint().showGui());
}
}
class PaintGUI extends JComponent {
//states defined by enum
enum SHAPE {RECTANGLE, LINE}
private SHAPE shape; // store state
private static final Color BACKGROUND_COLOR = Color.WHITE;
private int startX, startY, endX, endY; //shape coordinates
private Color color = Color.BLACK; //draw color
private BasicStroke stroke = new BasicStroke(3); //draw stroke
private boolean isClear = false;
public PaintGUI() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
//save coord x,y where mouse was pressed
startX = e.getX();
startY = e.getY();
endX = startX; endY = startY;
clear(); //clear draw board
}
});
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
//update end coord as mouse dragged
endX = e.getX();
endY = e.getY();
repaint(); //keep repainting while drag lasts
}
});
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// draw white on entire draw area to clear
g2.setColor(BACKGROUND_COLOR);
g2.fillRect(0, 0, getSize().width, getSize().height);
if(isClear || shape == null){
isClear = false;
return;
}
//draw using color , stroke and shape attributes
g2.setColor(color);
g2.setStroke(stroke);
switch (shape){
case RECTANGLE:
drawFilledRectangle(g2);
break;
case LINE:
drawLine(g2);
break;
default:
break;
}
}
public void clear() {
isClear = true;
repaint();
}
public void drawLine(Graphics2D g2) {
g2.drawLine( startX, startY, endX, endY);
repaint();
}
public void drawFilledRectangle(Graphics2D g2) {
//to allow rectangle dragged from bottom up and left to right
//use min x and min y as origin
int x = Math.min(startX, endX);
int y = Math.min(startY, endY);
int width = Math.abs(endX-startX); //to account for negative width
int height = Math.abs(endY-startY); //or height
g2.fillRect(x,y,width,height);
}
public void thin() {
setStroke(3);
}
public void thick() {
setStroke(10);
}
public void setStroke(int width) {
stroke = new BasicStroke(width);
repaint();
}
public void red() {
setColor(Color.red);
}
public void black() {
setColor(Color.black);
}
public void magenta() {
setColor(Color.magenta);
}
void setColor(Color color){
this.color = color;
repaint();
}
void setShape(SHAPE shape) {
this.shape = shape;
clear();
}
}

Wrap image to Jframe

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

More JPanel and background image

Should I set a background with a central start button. When click on button "start" you must load a "bersaglio" made in another class.
When I run it does not appear the background image but only the start button, I also tried to change the path of the image. Also, when I click on the button shows a "bersaglio".
Where am I wrong?
Home class
public class Home extends JFrame implements ActionListener{
JFrame frame;
JButton b1;
public Home(){
frame= new JFrame();
frame.setSize(200, 200);
frame.setTitle("Bersaglio");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//aggiungo lo sfondo e il bottone
b1=new JButton("START");
Sfondo sfondo=new Sfondo();
JPanel panelsecondo=new JPanel();
panelsecondo.add(b1,BorderLayout.CENTER);
sfondo.add(panelsecondo);
frame.getContentPane().add(sfondo);
b1.addActionListener(this); //aggiungo ascoltatore
frame.pack();
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
System.out.println("entra");
//bersaglio
Bersaglio bersaglio = new Bersaglio();
frame.add(bersaglio);
repaint();
}
}
Sfondo class
class Sfondo extends JPanel{
Image img;
public Sfondo(){
img = Toolkit.getDefaultToolkit().createImage("\\Esdicembre\\EsVacanze\\sfondo");
loadImage(img);
}
private void loadImage(Image img) {
try {
MediaTracker mt = new MediaTracker(this);
mt.addImage(img, 0);
mt.waitForID(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected void paintComponent(Graphics g) {
//setOpaque(false);
g.drawImage(img, 0, 0, null);
super.paintComponent(g);
}
}
class Bersaglio
public class Bersaglio extends JComponent implements MouseListener {
Ellipse2D.Double circle;
Ellipse2D.Double circle1;
Ellipse2D.Double circle2;
Ellipse2D.Double circle3;
/*public void setup(){
x=0;
y=0;
}
/*Color c;
int hight;
int weight;
public Circle() {
super();
}
public Circle(int x,int y,int hight,int weight) {
this.x=x;
this.y=y;
this.hight=hight;
this.weight=weight;
} */
public void paintComponent(Graphics g){
Graphics2D g2;
g2 = (Graphics2D) g;
g2.setColor(Color.BLUE);
circle1 = new Ellipse2D.Double(30, 30, 100, 100);
g2.fill(circle1);
//c1.fillOval(30,30,100,100);
//secondo cerchio medio
g2.setColor(Color.RED);
circle2 = new Ellipse2D.Double(50,50,60,60);
g2.fill(circle2);
//c1.fillOval(50,50,60,60);
//terzo cerchio piccolo
g2.setColor(Color.BLACK);
circle3 = new Ellipse2D.Double(70,70,20,20);
g2.fill(circle3);
//c1.fillOval(70,70,20,20);
addMouseListener(this);
//scrivere qualcosa
//g2.drawString("Ciao", 50, 100);
}
public void mouseClicked (MouseEvent e) {
//x = e.getX();
//y = e.getY();
Point p = e.getPoint();
if(circle3.contains(p)) {
System.out.println("Circle3 contains point");
}else{
if(circle2.contains(p)) {
System.out.println("Circle2 contains point");
}else {
if(circle1.contains(p)) {
System.out.println("Circle1 contains point");
}
}
}
Graphics g = getGraphics();
Graphics2D g2 = (Graphics2D) g;
circle = new Ellipse2D.Double(p.getX(),p.getY(),10,10);
g2.fill(circle);
revalidate();
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}

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