How to Zoom specific area of Image on Canvas in Swing - java

I want to Zoom specific area on image. which is selected by the user. image display on canvas using Swing. i already done full image zoom on canvas but can't implement specific area zoom.
please help

Canvas is awt not swing. Try JPanel instead. Example.
But if you already done full image zoom, try to make the same on a sub-image.
BufferedImage.getSubimage(x, y, w, h);
EDIT
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Example {
private Point startPoint = new Point(0, 0);
private Point rectLocale = new Point();
private Dimension rectSize = new Dimension();
private int zoom = 80;
private BufferedImage capture = null;
private BufferedImage raw;
public Example() throws Exception {
raw = new Robot().createScreenCapture(new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize()));
MouseBehavior behavior = new MouseBehavior();
JPanel b = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(500, 500);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = ((Graphics2D) g);
g2d.drawImage(raw, 0, 0, null);
if (capture != null) {
int width2 = (int) (rectSize.width + rectSize.width * (zoom / 500d));
int height2 = (int) (rectSize.height + rectSize.height * (zoom / 500d));
int x2 = rectLocale.x - ((width2 - rectSize.width) / 2);
int y2 = rectLocale.y - ((height2 - rectSize.height) / 2);
Image scaledInstance = capture.getScaledInstance(
width2, height2, Image.SCALE_AREA_AVERAGING);
g2d.drawImage(scaledInstance, x2, y2, null);
g2d.drawRect(x2, y2, width2, height2);
} else {
g2d.draw(new Rectangle(rectLocale, rectSize));
}
}
};
b.addMouseMotionListener(behavior);
b.addMouseListener(behavior);
b.addMouseWheelListener(behavior);
JFrame f = new JFrame();
f.setLocation(10, 10);
f.setDefaultCloseOperation(3);
f.add(b);
f.pack();
f.setVisible(true);
}
private class MouseBehavior extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
rectLocale = new Point();
rectSize = new Dimension();
capture = null;
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point currentPoint = e.getPoint();
rectSize.width = Math.abs(currentPoint.x - startPoint.x);
rectSize.height = Math.abs(currentPoint.y - startPoint.y);
if (e.isShiftDown()) {
rectSize.width = rectSize.height = Math.min(
rectSize.width, rectSize.height);
int dx = startPoint.x - rectSize.width;
int dy = startPoint.y - rectSize.height;
rectLocale.x = startPoint.x < currentPoint.x ? startPoint.x
: Math.max(dx, dy);
rectLocale.y = startPoint.y < currentPoint.y ? startPoint.y
: Math.min(dx, dy);
} else {
rectLocale.x = Math.min(currentPoint.x, startPoint.x);
rectLocale.y = Math.min(currentPoint.y, startPoint.y);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rectSize.width <= 0 || rectSize.height <= 0) {
capture = null;
} else {
capture = raw.getSubimage(Math.max(0, rectLocale.x),
Math.max(0, rectLocale.y), rectSize.width, rectSize.height);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
zoom = Math.min(2000, Math.max(0, zoom + e.getUnitsToScroll() * 10));
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Example example = new Example();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

Related

Drawing shapes in JPanel over an image

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

Why is this graphics object not painting? (What am i doing wrong?)

So I am writing a program in Java, and one of the important things it needs to be able to do is render multiple objects onto the screen that can be dragged and dropped by the user. I have made a class (pasted below), but when I try to initialise one with
new DragNode();
it doesn't work.
Can someone please tell me what I am doing wrong?
Thanks,
Sam
public static class DragNode extends JLabel{
public static final long serialVersionUID=155L;
public class MA extends MouseAdapter{
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
System.out.println("Mouse pressed on rectangle");
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
public int x,y;
Rectangle rect,area;
int preX,preY;
boolean firstTime=true;
boolean pressOut=false;
private Dimension dim=getGraphPanelSize();
private Image Node_Sprite;
public DragNode(){
init();
}
public DragNode(int x,int y){
this.x=x;
this.y=y;
init();
}
public void init(){
//setBackground(Color.GRAY);
setOpaque(false);
addMouseMotionListener(new MA());
addMouseListener(new MA());
rect = new Rectangle(x, y, 50, 50);
area=new Rectangle(dim);
try{
Node_Sprite=ImageIO.read(new File("Node_Sprite.png"));
}catch(IOException ioe){}
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, rect.getWidth(), rect.getHeight())) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + rect.getWidth()) > area.getWidth()) {
new_x = (int) area.getWidth() - (int) (rect.getWidth() - 1);
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + rect.getHeight()) > area.getHeight()) {
new_y = (int) area.getHeight() - (int) (rect.getHeight() - 1);
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
if (firstTime) {
rect.setLocation(x,y);
firstTime = false;
}
g2d.setColor(new Color(0,0,0,0));
g2d.drawImage(Node_Sprite, rect.x,rect.y,50,50,null);
}
}
When I replace the code for drawing the rectangle with
g2d.setColor(Color.red);
g2d.fillRect( rect.x, rect.y, 50, 50);
// g2d.drawImage(Node_Sprite, rect.x, rect.y, 50, 50, null);
It is drawn and can be dragged in the x-direction. So there might be something wrong with your image (does it exist in the specified folder?). I expected the dragging to be in both directions, so there might be an issue there as well for the y-direction.
EDIT: Ok, I tried it with an image as well, works well. I also saw that your "borders" 'dim' are set very narrow, so I increased them to 300/300 so I can drag around my image in both axis.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
public class DragNode extends JLabel {
public static final long serialVersionUID = 155L;
public static void main(String[] args) {
JLabel node = new DragNode();
JFrame frame = new JFrame("blupp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new MigLayout(""));
frame.getContentPane().add(node, "grow, push");
frame.setLocationRelativeTo(null);
frame.setSize(new Dimension(500, 300));
frame.setVisible(true);
}
public class MA extends MouseAdapter {
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
System.out.println("Mouse pressed on rectangle");
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
public int x, y;
Rectangle rect, area;
int preX, preY;
boolean firstTime = true;
boolean pressOut = false;
private Dimension dim = new Dimension(300, 300);
private Image Node_Sprite;
public DragNode() {
init();
}
public DragNode(int x, int y) {
this.x = x;
this.y = y;
init();
}
public void init() {
//setBackground(Color.GRAY);
setOpaque(false);
addMouseMotionListener(new MA());
addMouseListener(new MA());
rect = new Rectangle(x, y, 50, 50);
area = new Rectangle(dim);
try {
Node_Sprite = ImageIO.read(new File("Node_Sprite.png"));
} catch (IOException ioe) {}
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, rect.getWidth(), rect.getHeight())) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + rect.getWidth()) > area.getWidth()) {
new_x = (int) area.getWidth() - (int) (rect.getWidth() - 1);
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + rect.getHeight()) > area.getHeight()) {
new_y = (int) area.getHeight() - (int) (rect.getHeight() - 1);
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.green);
// g2d.fillRect(10, 10, 100, 100);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
if (firstTime) {
rect.setLocation(x, y);
firstTime = false;
}
g2d.setColor(Color.red);
// g2d.fillRect( rect.x, rect.y, 50, 50);
g2d.drawImage(Node_Sprite, rect.x, rect.y, 50, 50, null);
}
}
Not sure why you are extending JLabel. You are not using the label to paint text or an Icon. Instead you are actually doing the custom painting yourself so you should be extending JComponent.
Or the other approach is to just use a JLabel to display the image and then create your listener to drag the label to a new location and let the label to the painting. You can check out Component Mover which allows you to drag any component.

Getting the (starting) X and Y coordinates of a Path2D shape drawn on Jpanel

So, I have a program where I can add shapes to JPanel using Path2D objects and then I can click and drag them around. What I want to do is be able to find the final X and Y coordinates of the shape AFTER it has been drug. The coordinates need to be the top-left coordinates. Any ideas?
// add a circle to center of the screen
public void addCircle(int width, int height) {
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
getHeight() / 2 - height / 2, width, height), true);
shapes.add(circ);
repaint();
}
..................
//paint all shapes
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.draw(shape);
}
}
..................
// if the mouse click is in the circle, set pressed=true
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (int i = 0; i < shapes.size(); i++) {
if (shapes.get(i) != null
&& shapes.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
}
}
//if pressed=true, move circle with mouse
#Override
public void mouseDragged(MouseEvent e) {
if (pressed && !lineSelected) {
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
//I need to find the new coordinates here!!!!!!!!!!!
repaint();
}
}
Full Code
class Canvas extends JPanel {
private static final long serialVersionUID = 1L;
private List<Path2D> shapes = new ArrayList<Path2D>();
private int currentIndex;
private Point lineStartingPoint = new Point();
private Point lineEndingPoint = new Point();
private boolean drawing;
private boolean lineSelected;
private Path2D.Double linePath;
private Shapes myShapes = new Shapes();
private List<Path2D> circles = new ArrayList<Path2D>();
public Canvas() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
public void setList(ArrayList<UMLCircle> shapes) {
}
public List<UMLCircle> getList() {
return null;
}
public void addSquare(int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
shapes.add(rect2);
repaint();
}
public void addLine() {
lineSelected = true;
repaint();
}
public void addCircle(int width, int height) {
myShapes.addCircle(getWidth() / 2 - width / 2, getHeight() / 2 - height
/ 2, width, height);
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
getHeight() / 2 - height / 2, width, height), true);
circles.add(circ);
shapes.add(circ);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
if (lineSelected) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(2));
g2.drawLine(lineStartingPoint.x, lineStartingPoint.y,
lineEndingPoint.x, lineEndingPoint.y);
}
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.draw(shape);
}
}
class MyMouseAdapter extends MouseAdapter {
private boolean pressed = false;
private Point point;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (int i = 0; i < shapes.size(); i++) {
if (shapes.get(i) != null
&& shapes.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
if (circles.get(i) != null
&& circles.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
}
if (lineSelected) {
drawing = true;
lineStartingPoint = e.getPoint();
lineEndingPoint = lineStartingPoint;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed && !lineSelected) {
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
myShapes.updateCircleLocation(currentIndex, point.x, point.y);
System.out.println(point.x + " " + point.y);
repaint();
}
if (drawing) {
lineEndingPoint = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (drawing && lineSelected) {
drawing = false;
lineSelected = false;
lineEndingPoint = e.getPoint();
linePath = new Path2D.Double();
linePath.moveTo(lineStartingPoint.getX(),
lineStartingPoint.getY());
linePath.lineTo(lineEndingPoint.getX(), lineEndingPoint.getY());
shapes.add(linePath);
repaint();
}
pressed = false;
}
}
}
EDIT
Calculation for offset:
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
shapes.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
int newXPos = e.getX() - deltaX; // final X pos
int newXPos = e.getX() - deltaX; // final Y pos
Before you can do anything, you need to know the offset of the mouse click from the corner of the shape, this will allow you to drag the object so it doesn't suddenly "jump" to your current mouse position...
#Override
public void mousePressed(MouseEvent e) {
//...
for (Shape shape : myShapes) {
//...
this.point = e.getPoint();
int deltaX = point.x - shape.getBounds().x;
int deltaY = point.y - shape.getBounds().y;
offset = new Point(deltaX, deltaY);
//...
}
}
}
Then, you would calculate the delta of change, between the current mouse position and the offset. Because you're applying a translate, you also need to subtract the shape's current location, as the translation is based on the shape's current location and we only want to apply the amount of change
#Override
public void mouseDragged(MouseEvent e) {
if (pressed) {
int index = myShapes.indexOf(clickedShape);
myShapes.remove(index);
int deltaX = e.getPoint().x - offset.x;
int deltaY = e.getPoint().y - offset.y;
clickedShape = new Path2D.Double(clickedShape,
AffineTransform.getTranslateInstance(
deltaX - clickedShape.getBounds().x,
deltaY - clickedShape.getBounds().y));
myShapes.add(index, clickedShape);
point = e.getPoint();
repaint();
}
}
Now, having said all that, don't do this...
protected void paintComponent(Graphics g) {
//...
this.setOpaque(true);
this.setBackground(Color.WHITE);
Changing the state of the component from within the paint method can setup a infinite loop of repaint requests, which can chock your system. Also, the changes you make won't be applied to the current graphics context, as these properties are generally applied by the paint method...
And a working copy....
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
class Canvas extends JPanel {
private static final long serialVersionUID = 1L;
private boolean drawing;
private List<Shape> myShapes = new ArrayList<Shape>();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Canvas());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public Canvas() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
addSquare(100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void setList(ArrayList<Shape> shapes) {
}
public List<Shape> getList() {
return null;
}
public void addSquare(int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
myShapes.add(rect2);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Shape shape : myShapes) {
g2.draw(shape);
}
}
class MyMouseAdapter extends MouseAdapter {
private boolean pressed = false;
private Point point;
private Point offset;
private Shape clickedShape;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (Shape shape : myShapes) {
if (shape != null
&& shape.contains(e.getPoint())) {
System.out.println("Clicked");
pressed = true;
clickedShape = shape;
this.point = e.getPoint();
int deltaX = point.x - shape.getBounds().x;
int deltaY = point.y - shape.getBounds().y;
offset = new Point(deltaX, deltaY);
System.out.println(point + "x" + offset);
repaint();
break;
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed) {
int index = myShapes.indexOf(clickedShape);
myShapes.remove(index);
int deltaX = e.getPoint().x - offset.x;
int deltaY = e.getPoint().y - offset.y;
clickedShape = new Path2D.Double(clickedShape,
AffineTransform.getTranslateInstance(
deltaX - clickedShape.getBounds().x,
deltaY - clickedShape.getBounds().y));
myShapes.add(index, clickedShape);
point = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
offset = null;
pressed = false;
}
}
}

how to move and scale image by dragging it's edges?

I have post this question before also but this time I have added only required and necessary code only although the code is somewhat lengthy.
I want to load image in Jlabel and then after change image when user clicks next button. And when user want to move or scale image he can just easily do it by selecting image edges but it's not working.
All problem are solved except the scaling and moving image.
my code :
public class CopyOfPictureEditor extends JFrame
{
private static final long serialVersionUID = 6676383931562999417L;
String[] validpicturetypes = {"png", "jpg", "jpeg", "gif"};
Stack<File> pictures ;
JLabel label = new JLabel();
BufferedImage a = null;
JPanel panel = new JPanel();
public CopyOfPictureEditor()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
e.printStackTrace();
}
JMenuBar menubar = new JMenuBar();
JMenu toolsmenu = new JMenu(" File ");
final File dir = new File("");
final JFileChooser file;
file = new JFileChooser();
file.setCurrentDirectory(dir);
file.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
file.showOpenDialog(panel);
String path = file.getSelectedFile().getAbsolutePath();
System.out.println(path);
pictures= getFilesInFolder(path.toString());
JButton NEXT = new JButton("");
NEXT.setToolTipText("Next Image");
Image imgn = null;
try
{
imgn = ImageIO.read(getClass().getResource("/images/next12.png"));
}catch (IOException e) {
e.printStackTrace();
}
NEXT.setIcon(new ImageIcon(imgn));
JPanel buttonPane = new JPanel();
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
NEXT.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
nextImage();
}
});
buttonPane.add(NEXT);
getContentPane().add(buttonPane, BorderLayout.SOUTH);
setJMenuBar(menubar);
menubar.add(toolsmenu);
panel.add(label,BorderLayout.CENTER);
add(panel);
setTitle("Aero Picture Editor");
setVisible(true);
setPreferredSize(getPreferredSize());
setLocation(0,0);
label.addMouseListenet(new MouseHandler());
label.addMouseMotionListenet(new MouseHandler());
}
public Stack<File> getFilesInFolder(String startPath){
File startFolder = new File(startPath);
Stack<File> picturestack = new Stack<File>();
String extension;
int dotindex;
for (File file : startFolder.listFiles()) {
extension = "";
dotindex = file.getName().lastIndexOf('.');
if (dotindex > 0) {
extension = file.getName().substring(dotindex + 1);
for (String filetype : validpicturetypes){
if (extension.equals(filetype)) {
picturestack.add(file);
}
}
}
}
return picturestack;
}
public void nextImage() {
String p;
File f;
try{
f= pictures.pop().getAbsoluteFile();
a=ImageIO.read(f);
p = f.getPath();
System.out.println(p);
} catch (IOException e1) {
e1.printStackTrace();
}
ImageIcon image = new ImageIcon(a);
label.setIcon(image);
repaint();
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - a.getWidth()) / 2;
int y = (getHeight() - a.getHeight()) / 2;
AffineTransform at = new AffineTransform();
at.translate(x, y);
g2d.setTransform(at);
g2d.drawImage(a, 0, 0, this);
g2d.dispose();
}
public enum MouseAction {
Move(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)),
ResizeSouth(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)),
ResizeNorth(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)),
ResizeEast(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)),
ResizeWest(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)),
ResizeNorthEast(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)),
ResizeNorthWest(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)),
ResizeSouthEast(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)),
ResizeSouthWest(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
private Cursor cursor;
private MouseAction(Cursor cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return cursor;
}
}
public class MouseHandler extends MouseAdapter
{
private MouseAction action;
private Point clickPoint;
private boolean ignoreMoves;
protected void updateAction(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int width = getWidth();
int height = getHeight();
if (x < 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (x > width - 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (y < 10) {
action = MouseAction.ResizeNorth;
} else if (x < 10 && y > height - 10) {
action = MouseAction.ResizeSouthWest;
} else if (x > width - 10 && y > height - 10) {
action = MouseAction.ResizeSouthEast;
} else if (y > height - 10) {
action = MouseAction.ResizeSouth;
} else if (x < 10) {
action = MouseAction.ResizeWest;
} else if (x > width - 10) {
action = MouseAction.ResizeEast;
} else {
action = MouseAction.Move;
} setCursor(action.getCursor());
}
#Override
public void mouseMoved(MouseEvent e) {
if (!ignoreMoves)
{
updateAction(e);
}
}
#Override
public void mousePressed(MouseEvent e) {
updateAction(e);
ignoreMoves = true;
clickPoint = e.getPoint();
repaint();
System.out.println(e.getX());
System.out.println(e.getY());*/
}
#Override
public void mouseReleased(MouseEvent e) {
clickPoint = null;
ignoreMoves = false;
}
#Override
public void mouseDragged(MouseEvent e) {
switch (action) {
case Move: {
Point p = e.getPoint();
p.x -= clickPoint.x;
p=SwingUtilities.convertPoint(label, p, null);
setLocation(p);
}
break;
case ResizeWest: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
setSize(width, getHeight());
setLocation(x, getY());
revalidate();
}
break;
case ResizeEast: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() + xDelta;
setSize(width, getHeight());
revalidate();
clickPoint = p;
}
break;
case ResizeNorth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() - yDelta;
int y = getY() + yDelta;
setSize(getWidth(), height);
setLocation(getX(), y);
revalidate();
}
break;
case ResizeSouth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() + yDelta;
setSize(getWidth(), height);
revalidate();
clickPoint = p;
}
break;
}
}
#Override
public void mouseExited(MouseEvent e)
{
}
}
}
Found this one:
label.addMouseListener(new MouseHandler());
label.addMouseMotionListener(new MouseHandler());
Since you set your clickPoint in mousePressed and want to have it in mouseDragged, it should be the same object. You should actually get some nullpointers in mouseDragged?
Hard to see without complete code, but for one, you're calling setSize and setLocation on the Window itself in your MouseDragged method. If you want to get the object the user clicked on you need to get it from e.getSource(), like:
public void mouseDragged(MouseEvent e){
JLabel l = (JLabel)e.getSource();
switch(action){
case ResizeWest:
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
l.setSize(width, getHeight()); // call setSize on JLabel l
l.setLocation(x, getY());
l.revalidate();
break;
}
Incidentally, why are you using a JLabel for this? I would use a Java object that draws itself onto the JFrame using the JFrame's graphics context.

Java: Resizing a component without repainting?

I'm working on a Java program that displays a map (inherited from JComponent) within a JScrollPane. When the MouseWheelListener fires, the map zooms and the JScrollPane's viewport is adjusted to center on the location of the mouse.
This all works fine, except that the call to setSize(Dimension d) forces the map to repaint immediately before the view is adjusted, causing a "stutter." However, I cannot adjust the view until after setSize has completed execution or the calculations for "centering" the viewport will be haywire (due to getHeight() and getWidth() calls,) therefore the viewport adjustment is within a runnable called with invokeLater.
I would like to find a way to move directly from the previous map size and viewport location to the new view, without seeing the scene repainted twice.
setIgnoreRepaint(boolean) did not work for me. Is there another way to go about this?
EDIT: Here's what I worked up from your sample code that replicates my issue, although not as noticably as there's far less computation going on in the drawing. If you scroll rapidly over the image, you'll see that there's a brief stutter between the resizing of the hexagons to their new size and the adjustment of the viewport to its new position.
You can see the hexagons being re-drawn twice. (Once when the setSize() method is called and once when the setViewPosition() method is called.)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class ZoomWithSelectionInViewport implements MouseWheelListener{
private int zoom = 80;
JComponent b;
int hexSize = 3;
public ZoomWithSelectionInViewport() throws Exception{
b = new JComponent() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(700, 700);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = ((Graphics2D) g);
int vertOffsetX, vertOffsetY, horizOffsetX, horizOffsetY;
vertOffsetX = (int)((double)hexSize* Math.sqrt(3.0f));
vertOffsetY = (int)((double)-hexSize-1* Math.sqrt(3.0f)/2.0f);
horizOffsetX = (int) ((double)hexSize* Math.sqrt(3.0f));
horizOffsetY = (int) ((double)hexSize+1* Math.sqrt(3.0f)/2.0f);
for(int x = 0; x < 50; x++)
{
for(int y = 0; y < 50; y++)
{
int[] xcoords = new int[6]; int[] ycoords = new int[6];
for(int i = 0; i < 6; i++)
{
xcoords[i] = (int)((hexSize+x * horizOffsetX + y * vertOffsetX) + (double)hexSize * Math.cos(i * 2 * Math.PI / 6));
ycoords[i] = (int)(((getSize().height /2 )+ x * horizOffsetY + y * vertOffsetY) + (double)hexSize * Math.sin(i * 2 * Math.PI / 6));
}
g2d.setStroke(new BasicStroke(hexSize/2.5f));
g2d.setColor(Color.GRAY);
g2d.drawPolygon(xcoords, ycoords, 6);
}
}
}
};
JScrollPane view = new JScrollPane(b);
b.addMouseWheelListener(this);
JFrame f = new JFrame();
f.setLocation(10, 10);
f.setDefaultCloseOperation(3);
f.add(view);
f.setSize(500,500);
f.setVisible(true);
view.setWheelScrollingEnabled(false);
}
public void mouseWheelMoved(MouseWheelEvent e) {
zoom = 100*-Integer.signum(e.getWheelRotation());
if(hexSize - Integer.signum(e.getWheelRotation()) > 0)
hexSize-= Integer.signum(e.getWheelRotation());
Dimension targetSize = new Dimension(b.getWidth()+zoom,b.getHeight()+zoom);
b.setPreferredSize(targetSize);
b.setSize(targetSize);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JViewport tempView = (JViewport)b.getParent();
tempView.setViewPosition(new Point(b.getWidth()/2,b.getHeight()/2));
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
ZoomWithSelectionInViewport example = new ZoomWithSelectionInViewport();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
my curiosity, no idea what's happends, could you please use this SSCCE add there your issues and edit with the code your question
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class ZoomWithSelectionInViewport {
private Point startPoint = new Point(0, 0);
private Point rectLocale = new Point();
private Dimension rectSize = new Dimension();
private int zoom = 80;
private BufferedImage capture = null;
private BufferedImage raw;
public ZoomWithSelectionInViewport() throws Exception {
raw = new Robot().createScreenCapture(new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize()));
MouseBehavior behavior = new MouseBehavior();
JPanel b = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
public Dimension getMinimumSize() {
return new Dimension(500, 500);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = ((Graphics2D) g);
g2d.drawImage(raw, 0, 0, null);
if (capture != null) {
int width2 = (int) (rectSize.width + rectSize.width * (zoom / 500d));
int height2 = (int) (rectSize.height + rectSize.height * (zoom / 500d));
int x2 = rectLocale.x - ((width2 - rectSize.width) / 2);
int y2 = rectLocale.y - ((height2 - rectSize.height) / 2);
Image scaledInstance = capture.getScaledInstance(
width2, height2, Image.SCALE_AREA_AVERAGING);
g2d.drawImage(scaledInstance, x2, y2, null);
g2d.drawRect(x2, y2, width2, height2);
} else {
g2d.draw(new Rectangle(rectLocale, rectSize));
}
}
};
b.addMouseMotionListener(behavior);
b.addMouseListener(behavior);
b.addMouseWheelListener(behavior);
JFrame f = new JFrame();
f.setLocation(10, 10);
f.setDefaultCloseOperation(3);
f.add(b);
f.pack();
f.setVisible(true);
}
private class MouseBehavior extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
rectLocale = new Point();
rectSize = new Dimension();
capture = null;
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point currentPoint = e.getPoint();
rectSize.width = Math.abs(currentPoint.x - startPoint.x);
rectSize.height = Math.abs(currentPoint.y - startPoint.y);
if (e.isShiftDown()) {
rectSize.width = rectSize.height = Math.min(rectSize.width, rectSize.height);
int dx = startPoint.x - rectSize.width;
int dy = startPoint.y - rectSize.height;
rectLocale.x = startPoint.x < currentPoint.x ? startPoint.x : Math.max(dx, dy);
rectLocale.y = startPoint.y < currentPoint.y ? startPoint.y : Math.min(dx, dy);
} else {
rectLocale.x = Math.min(currentPoint.x, startPoint.x);
rectLocale.y = Math.min(currentPoint.y, startPoint.y);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rectSize.width <= 0 || rectSize.height <= 0) {
capture = null;
} else {
capture = raw.getSubimage(Math.max(0, rectLocale.x),
Math.max(0, rectLocale.y), rectSize.width, rectSize.height);
}
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
zoom = Math.min(2000, Math.max(0, zoom + e.getUnitsToScroll() * 10));
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).repaint();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
ZoomWithSelectionInViewport example = new ZoomWithSelectionInViewport();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
an alternative could be
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
public class ZoomDemo {
private PaintSurface canvas = new PaintSurface();
private JFrame frame = new JFrame();
private AffineTransform aT = new AffineTransform();
private Point2D p1 = null;
private Point2D p2 = null;
public ZoomDemo() {
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
ScaleListener scaleListener = new ScaleListener();
canvas.addMouseWheelListener(scaleListener);
canvas.addMouseListener(scaleListener);
frame.add(canvas);
frame.setVisible(true);
}
public class ScaleListener extends MouseAdapter {
private double scale = 1;
#Override
public void mouseClicked(MouseEvent e) {
p1 = e.getPoint();
try {
p2 = aT.inverseTransform(p1, new Point2D.Double());
/*
* p1 is the point relative to canvas where the user physically
* held the mouse.
*
* Since you may want to deal with a virtual mouse location
* relative to an untransformed canvas, you inverse transform p1
* to p2.
*
* For example: when the user held the mouse over, let's say,
* the displayed left upper corner of the red rectangle.
*
* p2 now will point to the upper left corner of the red
* rectangle in an untransformed canvas.
*/
applyScale();
} catch (NoninvertibleTransformException e1) {
e1.printStackTrace();
}
canvas.repaint();
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (p1 != null && p2 != null) {
scale -= (0.05 * e.getWheelRotation());
if (scale > 5) {
scale = 5;
}
if (scale < 1) {
scale = 1;
aT.setToIdentity();
} else {
applyScale();
}
canvas.repaint();
}
}
private void applyScale() {
aT.setToIdentity();
// *** variation one (your implementation)
aT.translate(p1.getX(), p1.getY());
aT.scale(scale, scale);
aT.translate(-p2.getX(), -p2.getY());
// *** variation two
// aT.translate(p1.getX(), p1.getY());
// aT.scale(scale, scale);
// aT.translate(-p1.getX(), -p1.getY());
// *** variation three
// aT.translate(p2.getX(), p2.getY());
// aT.scale(scale, scale);
// aT.translate(-p2.getX(), -p2.getY());
}
}
public class PaintSurface extends JComponent {
private static final long serialVersionUID = 1L;
{
this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
/*
* Override paintComponent, not paint!!!
*/
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
try {
g2.setColor(Color.black);
g2.fillRect(0, 0, getWidth(), getHeight());
// g2.setTransform(aT); <<<<<<<<< !!!!!!!
/*
* A transform (translation for example) may already have been
* applied to the Graphics object by a parent. This is removed
* by setTransform.
*/
g2.transform(aT); // <<<<<<<<<< !!!!!!!
g2.setColor(Color.red);
g2.drawRect(50, 50, 100, 100);
g2.setColor(Color.blue);
g2.drawRect(200, 200, 150, 50);
if (p2 != null) {
g2.setColor(Color.green);
g2.fill(new Rectangle2D.Double(p2.getX() - 4, p2.getY() - 4, 8, 8));
}
} finally {
g2.dispose();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ZoomDemo zoomDemo = new ZoomDemo();
}
});
}
}
same question,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
//http://stackoverflow.com/questions/6819243/jscrollpane-jumping-when-scrollbars-start-being-used
public class LockViewPortToPoint extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] arg) {
LockViewPortToPoint lockViewPortToPoint = new LockViewPortToPoint();
}
public LockViewPortToPoint() {
initComponents();
setVisible(true);
}
private void initComponents() {
setLayout(new BorderLayout());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 600);
setPreferredSize(new Dimension(600, 600));
add(new TopPanel());
}
private class TopPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JScrollPane scrollPane;
TopPanel() {
setPreferredSize(new Dimension(500, 500));
scrollPane = new JScrollPane(new InteriorPanel());
scrollPane.setPreferredSize(new Dimension(500, 500));
scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(10, 490));
scrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(490, 10));
scrollPane.setWheelScrollingEnabled(false);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
}
private class InteriorPanel extends JPanel {
private static final long serialVersionUID = 1L;
private double scale = 10.0;
private final double scaleModifier = 0.1;
private final int width = 10;
private Point loc = new Point(0, 0);
private final int SIZE = 10;
private Point orig = new Point(250, 250);
InteriorPanel() {
super(true);
setPreferredSize(new Dimension((int) (scale * width * SIZE), (int) (scale * width * SIZE)));
this.addMouseWheelListener(new MapMouseWheelListener());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2D.scale(scale, scale);
for (int row = 0; row <= SIZE; row++) {
for (int col = 0; col < SIZE; col++) {
if ((col + row) % 2 == 0) {
g2D.setColor(Color.white);
} else {
g2D.setColor(Color.black);
}
g2D.fillRect(col * width, row * width, width, width);
}
}
}
private void incrementScale(int notches) {
double modifier = 0;
final double prevScale = scale;
if (notches != 0) {
modifier = 1.0 + -notches / Math.abs(notches) * scaleModifier;
}
scale *= Math.pow(modifier, Math.abs(notches));
/*if (scale * width < 1) {
scale = 1.0/width;
} else if (scale * width * 3 > parentHeight || scale * width * 3 > parentWidth) {
if (parentHeight > parentWidth) {
scale = parentWidth / 3.0 / width;
} else {
scale = parentHeight / 3.0 / width;
}
} else if (scale * width * SIZE < parentWidth) {
scale = parentWidth / (double)SIZE / width;
} else if (scale * width * SIZE < parentHeight) {
scale = parentHeight / (double)SIZE / width;
}*/
setPreferredSize(new Dimension((int) (scale * width * SIZE), (int) (scale * width * SIZE)));
orig = new Point(((int) (scale * width * SIZE)) / 2, ((int) (scale * width * SIZE) / 2));
final JViewport viewport = ((JViewport) (getParent().getParent().getComponent(0)));
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
viewport.setViewPosition(new Point(
orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
orig.y - (int) Math.round(loc.y * (1 - scale / prevScale))));
}
});
/*viewport.scrollRectToVisible(new Rectangle(new Point(
orig.x - (int) Math.round(loc.x * (1 - scale / prevScale)),
orig.y - (int) Math.round(loc.y * (1 - scale / prevScale))))); */
System.out.println(orig + "\n " + loc + "\n " + (1 - scale / prevScale));
revalidate();
repaint();
}
private class MapMouseWheelListener implements MouseWheelListener {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
loc = e.getPoint();
incrementScale(e.getWheelRotation());
}
}
}
}
another example
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
//http://stackoverflow.com/questions/115103/how-do-you-implement-position-sensitive-zooming-inside-a-jscrollpane
public class FPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private Dimension preferredSize = new Dimension(400, 400);
private Rectangle2D[] rects = new Rectangle2D[50];
public static void main(String[] args) {
JFrame jf = new JFrame("test");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(400, 400);
jf.add(new JScrollPane(new FPanel()));
jf.setVisible(true);
}
public FPanel() {
// generate rectangles with pseudo-random coords
for (int i = 0; i < rects.length; i++) {
rects[i] = new Rectangle2D.Double(
Math.random() * .8, Math.random() * .8,
Math.random() * .2, Math.random() * .2);
}
// mouse listener to detect scrollwheel events
addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
updatePreferredSize(e.getWheelRotation(), e.getPoint());
}
});
}
private void updatePreferredSize(int wheelRotation, Point stablePoint) {
double scaleFactor = findScaleFactor(wheelRotation);
scaleBy(scaleFactor);
Point offset = findOffset(stablePoint, scaleFactor);
offsetBy(offset);
getParent().doLayout();
revalidate();
repaint();
}
private double findScaleFactor(int wheelRotation) {
double d = wheelRotation * 1.08;
return (d > 0) ? 1 / d : -d;
}
private void scaleBy(double scaleFactor) {
int w = (int) (getWidth() * scaleFactor);
int h = (int) (getHeight() * scaleFactor);
preferredSize.setSize(w, h);
}
private Point findOffset(Point stablePoint, double scaleFactor) {
int x = (int) (stablePoint.x * scaleFactor) - stablePoint.x;
int y = (int) (stablePoint.y * scaleFactor) - stablePoint.y;
return new Point(x, y);
}
private void offsetBy(Point offset) {
Point location = getLocation();
setLocation(location.x - offset.x, location.y - offset.y);
}
#Override
public Dimension getPreferredSize() {
return preferredSize;
}
private Rectangle2D r = new Rectangle2D.Float();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
int w = getWidth();
int h = getHeight();
for (Rectangle2D rect : rects) {
r.setRect(rect.getX() * w, rect.getY() * h,
rect.getWidth() * w, rect.getHeight() * h);
((Graphics2D) g).draw(r);
}
}
}

Categories

Resources