How do I draw the unique rectangle(cube) inside the oval:
http://i.stack.imgur.com/pmHTl.jpg
For me it is tricky to use graphics to draw a rectangle such as the one shown. Any advice on what to do.
Ok. I will try to make myself as clear as I can. What I have so far are the orange ovals and the slim gray oval that is behind it. I only need to create one of these "dots" in a class and i will make many objects of them. The Task I need help in is drawing the "rectangle" shape you see that is in the orange dot using J Component possibly. By request I will add a picture of what I have so far if this edit does not fulfill the need for you to understand my problem.
Thanks
Edit : Here is the Code that I have for creating the ovals if that is of interest to you-
public void paint(Graphics g) {
Color c = (Color.orange);
g.setColor(Color.gray);
g.fillOval(3,3,60,60);
g.setColor(c);
g.fillOval(0,0,60,60);
}
Edit: My Attempt at an SSCCE -->
NanoBot Class(Where I am Creating the Bot in paint)
/**
* #author (Omar Ahmed)
*/
import javax.swing.*;
import java.awt.*;
public class NanoBot extends Image
{
public NanoBot(int x, int y, int w, int h)
{
super(x,y,w,h);
}
public void paint(Graphics g) {
Color c = (Color.orange);
g.setColor(Color.gray);
g.fillOval(3,3,60,60);
g.setColor(c);
g.fillOval(0,0,60,60);
//g.setColor(Color.black);
//g.fillOval(10,20,10,10);
//g.fillOval(40,20,10,10);
}
}
And The Driver:
/** Bot Swarm
* Date: May, 2013
* Author: Omar Ahmed
*/
import java.awt.*;
import javax.swing.*;
public class Driver {
private JFrame win;
private NanoBot bot1;
public Driver() {
win = new JFrame(" Swarm ");
win.setLayout(null);
win.setVisible(true);
win.setBounds( 20, 20, 800, 700);
win.getContentPane().setBackground(Color.white);
bot1=new NanoBot(50,50,70,70);
win.add(bot1,0);
}
Hope This Helps
Your first step is to break down your requirements...
You need to draw 3 shapes, front, top, side.
The front's y position is offset by 0.412 of the overall height. It's width is 0.77 of the overall width.
The top's height is 0.412 of the overall height, and it has a horizontal inset of 0.2 of the overall width...
The side's x position is offset by 0.77 of the overall width and has an inset of 0.47 of the over all width.
This is all very important, as you want to ensure that the shapes can resize reasonably well...
Now, you could simply use Graphics#drawLine and Graphics#drawRectangle to build the shape, but that, to me, is a lot of work...
Instead the 2D Graphics is very powerful and contains many wonderful things, the one of interest today is the Shape API, which allows you to define many different shapes, which can be drawn or filled.
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.Shape;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestChip {
public static void main(String[] args) {
new TestChip();
}
public TestChip() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = 44;
int height = 17;
Front front = new Front(width, height);
Top top = new Top(width, height);
Side side = new Side(width, height);
draw(g2d, front, Color.BLACK, Color.YELLOW);
draw(g2d, top, Color.BLACK, Color.GRAY);
draw(g2d, side, Color.BLACK, Color.DARK_GRAY);
g2d.dispose();
}
protected void draw(Graphics2D g2d, Shape shape, Color foreground, Color background) {
g2d.setColor(background);
g2d.fill(shape);
g2d.setColor(foreground);
g2d.draw(shape);
}
}
public class Front extends Path2D.Float {
public Front(float width, float height) {
float frontWidth = width * 0.77f;
float yOffset = height * 0.412f;
moveTo(0, yOffset);
lineTo(frontWidth, yOffset);
lineTo(frontWidth, height);
lineTo(0, height);
closePath();
}
}
public class Side extends Path2D.Float {
public Side(float width, float height) {
float xOffset = width * 0.77f;
float inset = height * 0.47f;
moveTo(xOffset, inset);
lineTo(width, 0);
lineTo(width, inset);
lineTo(xOffset, height);
closePath();
}
}
public class Top extends Path2D.Float {
public Top(float width, float height) {
float inset = width * 0.2f;
float shapeHeight = height * 0.412f;
moveTo(inset, 0);
lineTo(width, 0);
lineTo(width - inset, shapeHeight);
lineTo(0, shapeHeight);
closePath();
}
}
}
Your job is to now go away, study the example, study the referenced tutorials, study the associated API docs and figure out how to align the above shape within you circle and draw it's legs...
A hint. Make a "Bug" class that knows how to renderer all this and simply translate the position of the Graphics as required...
Related
I am taking an introductory java class and I have an inheritance related problem. I have to implement a system that has classes for various figures. the superclass is Figures and subclasses are Circle, Box and Rectangle and I am supposed to output the figures in the JPanel. I have designed all the classes and my code is below but I need to define the center() method on the figure class which when called on an object should draw and also erase the object. so within the main method of the JPanel class, I want to use the center() method to draw the three shapes and use the wait(long timeout) method to make the shapes change to random positions after 15 seconds.
import java.awt.Graphics;
import javax.swing.JPanel;
public abstract class Figure extends JPanel {
protected int xCoord;
protected int yCoord;
public Figure() {
}
public void erase() {
}
public void draw() {
}
public void center() {
}
}
the rectangle sub class is:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Rectangle extends Figure {
int width;
int height;
public Rectangle() {
this.width = 0;
this.height = 0;
}
public Rectangle(int xCoord, int yCoord, int width, int height)
{
this.xCoord = xCoord;
this.yCoord = yCoord;
this.width = width;
this.height = height;
}
public void draw(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(xCoord, yCoord, width, height);
}
public void erase(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 0, 0);
}
}
the circle subclass:
public class Circle extends Figure {
private int radius;
public Circle ()
{
this.radius = 0;
}
public Circle (int xCoord, int yCoord, int radius)
{
this.xCoord = xCoord;
this.yCoord = yCoord;
this.radius = radius;
}
public void draw(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(xCoord, yCoord, radius, radius);
}
public void erase(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(0,0,0,0);
}
}
the box subclass:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Box extends Figure {
private int edgeLength;
public Box() {
this.edgeLength = 0;
}
public Box(int xCoord, int yCoord, int edgeLength)// Creating Rectangle
// Class given width and
// height
{
this.xCoord = xCoord;
this.yCoord = yCoord;
this.edgeLength = edgeLength;
}
public void draw(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(xCoord, yCoord, edgeLength, edgeLength);
}
public void erase(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 0, 0);
}
}
the JPanel class
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SamplePanel extends JPanel {
private static final int PANEL_HEIGHT = 400;
private static final int PANEL_WIDTH = 400;
Rectangle rect = new Rectangle(75, 85, 50,30);
Circle circle = new Circle(275, 75, 50);
Box box = new Box (75, 275, 50);
public SamplePanel() {
setPreferredSize(new Dimension(PANEL_HEIGHT, PANEL_WIDTH));
setBackground(Color.WHITE);
//Rectangle rect = new Rectangle(100, 100, 15,10);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
rect.draw(g);
circle.draw(g);
box.draw(g);
g.drawLine(200, 0, 200, 400);
g.drawLine(0, 200, 400, 200);
}
/**
* #param layout
*/
public SamplePanel(LayoutManager layout) {
super(layout);
}
/**
* #param isDoubleBuffered
*/
public SamplePanel(boolean isDoubleBuffered) {
super(isDoubleBuffered);
}
/**
* #param layout
* #param isDoubleBuffered
*/
public SamplePanel(LayoutManager layout, boolean isDoubleBuffered) {
super(layout, isDoubleBuffered);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Window Title Here");
SamplePanel panel = new SamplePanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
Figure box = new Box(75, 275, 50);
}
}
Answer...
How to use Swing Timers
It is safe to use within the context of Swing as it won't block the Event Dispatching Thread while waiting and will generate notifications within the context of the Event Dispatching Thread, making it safe to update the UI from.
Observations...
Your basic design, while correct in concept, is implemented in correctly. I'd would strongly discourage you from using JPanel in this way. Components have a particular life cycle which you're not managing correctly, which could cause no end of issues.
Instead, go right back to basics. What is it the shape should be able to?
public interface Figure {
public void draw(Graphics2D g2d);
public Rectangle getBounds();
public void setBounds(Rectangle bounds);
}
Here, it's capable of been painted and has a concept of size and position (yes, you can use an abstract class, but this removes all requirements on the base implementation, making it far more flexible)
Because I imagine most of the implementations are going to be basically the same, I can use an abstract class to implement the core functionality...
public abstract class AbstractFigure implements Figure {
private Rectangle bounds;
#Override
public Rectangle getBounds() {
return bounds;
}
#Override
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
}
Based on your needs, you might be able to create a few abstract classes which implement the functionality different, but the basic idea is to see what functionality is common to all the implementations and reduce the amount of duplicate code you generate.
Then you can start implementing your concrete classes...
public class RectangleFigure extends AbstractFigure {
public RectangleFigure(Rectangle bounds) {
setBounds(bounds);
}
#Override
public void draw(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.fill(getBounds());
}
}
But where's the "erase" method you ask? Well, erase is just the absence of painting, so, when you want to "erase" a shape, remove it from the painting process and repaint the container, shape is erased
This is suggests to me that you need to have a look at Painting in AWT and Swing and Performing Custom Painting to better understand how painting works in Swing.
"Where's the center method?" I hear you ask. Okay, you "could" have a center method in the Figure, the problem is, Figure has no concept of the parent container, is you'd have to pass the size of the container to it. Not difficult, I'd argue, however, this really isn't a function of the Figure, but a function of the container, so I'd have the center method implemented there, since you want to change the position of the Figures anyway, it makes sense (to me) to all that wrapped up in the container
So I'm trying to draw a curve that has a taper profile like this : y=
Since I'm using awt.Graphics2D, I only have the ability to draw shapes.
One way to draw curves is to draw curves is use use BĀ“ezier curves. Is there a way convert this or a awt trick I'm not familiar with ?
One option to draw a curve is point by point :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Curve extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
for (int x = 1; x <= 100; x++) {
int y = getY(x);
//2g does not support drawing a point so you draw a line
g2d.drawLine(x, y, x, y);
}
}
/**
*#param x
*#return
*/
private int getY(int x) {
//change to the function you want
return 50+ (100/(1+ (3* x)));
}
public static void main(String[] args) {
Curve points = new Curve();
JFrame frame = new JFrame("Curve");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(points);
frame.setSize(350, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I have a problem. I want to be able to zoom into my Graphics2D screen using the mouse wheel but I want to be able to translate the Graphics2D as well so that it's right on the spot that I scaled. Here's what's happening so far: "http://cdn.makeagif.com/media/6-11-2015/E0kYGY.gif" It's translating to the player's position correctly but I want it to be zoomable in and out with the scrolling of the mouse wheel. Here's the code I have so far to do it:
private AffineTransform getCamTransform()
{
AffineTransform t = new AffineTransform();
float a = 400 - player.getX();
float b = 250 - player.getY();
t.translate(a, b);
/*
* Here's where I want to scale using the zoom
* variable and also translate the g2d according
* to the zoom variable.
*/
return t;
}
private double zoom = 2.0D;
#Override
public void mouseWheelMoved(MouseWheelEvent e)
{
zoom += e.getPreciseWheelRotation();
}
This is just a small segment of the code I have. I have a method that draws everything to the screen but this is just to return the transform that must be applied to the camera. The transform is then set to the previous transform of the Graphics2D.
Let me know if there's an easier way to do this or I'm doing it all wrong. I do also want to be efficient on the CPU as well. Thanks to whoever answers!
The basic idea is, you want to make it appear as if the graphics is remaining centred within the viewable area. I first thought about trying to scale the translation points, and maybe that might work, but I couldn'y get it to work (3 year old wanting to read books didn't give me much time to experiment).
Basically, you need to add another translation in which moves the x/y point the appropriate amount based on the viewable area and the zoom so the image appears to remain stationary within the viewable area, then apply the zoom and the normal translation on-top of it...
double width = getWidth();
double height = getHeight();
double zoomWidth = width * zoom;
double zoomHeight = height * zoom;
double anchorx = (width - zoomWidth) / 2;
double anchory = (height - zoomHeight) / 2;
AffineTransform at = new AffineTransform();
at.translate(anchorx, anchory);
at.scale(zoom, zoom);
at.translate(-100, -100);
So, the anchorx/y represent the amount the resulting graphics would need be offset by, based on the viewable areas width and height, so that the image will remain "centred" within in it...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private double zoom = 1d;
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(new File("..."));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseWheelListener(new MouseAdapter() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getPreciseWheelRotation() < 0) {
zoom -= 0.1;
} else {
zoom += 0.1;
}
// zoom += e.getPreciseWheelRotation();
if (zoom < 0.01) {
zoom = 0.01;
}
repaint();
}
});
}
public String format(double value) {
return NumberFormat.getNumberInstance().format(value);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double width = getWidth();
double height = getHeight();
double zoomWidth = width * zoom;
double zoomHeight = height * zoom;
double anchorx = (width - zoomWidth) / 2;
double anchory = (height - zoomHeight) / 2;
AffineTransform at = new AffineTransform();
at.translate(anchorx, anchory);
at.scale(zoom, zoom);
at.translate(-100, -100);
g2d.setTransform(at);
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}
}
There's probably a really awesome mathematical formula which you could use instead, but me be dumb ;)
This question already has an answer here:
Collision detection with complex shapes
(1 answer)
Closed 8 years ago.
So, I have a program that draws Path2D circles onto JPanel. What I am trying to do is resize the circle when the user clicks and drags the bottom right of the circle. So, what I want is to detect when they are on the bottom-right outer edge of the circle, not the bottom-right of the bounds around the circle. Basically, I need to figure out how to do something like this:
I know how to do this with rectangles using getBounds() but when you use getBounds() on a circle, it will return the square around the circle and not the bounds of the actual circle. Any ideas on how I can get this to work? Thanks!
Here is a shortened, runnable version of my program:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
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;
public class Editor {
public static void main(String[] args) {
JFrame frame = new UMLWindow();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(30, 30, 1000, 700);
frame.getContentPane().setBackground(Color.white);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class UMLWindow extends JFrame {
Shapes shapeList = new Shapes();
Panel panel;
private static final long serialVersionUID = 1L;
public UMLWindow() {
addMenus();
panel = new Panel();
}
public void addMenus() {
getContentPane().add(shapeList);
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
shapeList.addCircle(100, 100);
}
}
// Shapes class, used to draw the shapes on the panel
// as well as implements the MouseListener for dragging
class Shapes extends JPanel {
private static final long serialVersionUID = 1L;
private List<Path2D> shapes = new ArrayList<Path2D>();
int currentIndex;
public Shapes() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
public void addCircle(int width, int height) {
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(442, 269, width, height), true);
shapes.add(circ);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.draw(shape);
}
}
class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
}
You'll want to brush up your trig (or google search like I did ;)). The basic concept is "relatively" easy, but I created a nice method to all the work for me...
This method...
public Point2D getPointOnEdge(float angel, Rectangle bounds) {
float radius = Math.max(bounds.width, bounds.height) / 2;
float x = radius;
float y = radius;
double rads = Math.toRadians((angel + 90));
// Calculate the outter point of the line
float xPosy = (float) (x + Math.cos(rads) * radius);
float yPosy = (float) (y + Math.sin(rads) * radius);
return new Point2D.Float(xPosy + bounds.x, yPosy + bounds.y);
}
Will calculate the x/y point that a given angle will appear on a circle, remember, this will ONLY work for circles!
I then use another method...
public Rectangle2D getActiveBounds(float angel, Rectangle bounds) {
Point2D p = getPointOnEdge(angel, bounds);
return new Rectangle2D.Double(p.getX() - 4, p.getY() - 4, 8, 8);
}
To calculate the "mouse zone" in which I would consider to be the bottom/right area, cause a single pixel is hard to find and simply use Rectangle#contains, passing it the current mouse location...
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Editor {
public static void main(String[] args) {
new Editor();
}
public Editor() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new UMLWindow();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(30, 30, 1000, 700);
frame.getContentPane().setBackground(Color.white);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class UMLWindow extends JFrame {
Shapes shapeList = new Shapes();
Panel panel;
private static final long serialVersionUID = 1L;
public UMLWindow() {
addMenus();
panel = new Panel();
}
public void addMenus() {
getContentPane().add(shapeList);
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
shapeList.addCircle(100, 100);
}
}
// Shapes class, used to draw the shapes on the panel
// as well as implements the MouseListener for dragging
public static class Shapes extends JPanel {
private static final long serialVersionUID = 1L;
private List<Path2D> shapes = new ArrayList<Path2D>();
int currentIndex;
private Point mousePoint;
public Shapes() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
public void addCircle(int width, int height) {
Path2D circ = new Path2D.Double();
circ.append(new Ellipse2D.Double(442, 269, width, height), true);
shapes.add(circ);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
for (Path2D shape : shapes) {
g2.setColor(Color.BLACK);
g2.draw(shape);
g2.setColor(Color.RED);
Rectangle2D bottomRight = getActiveBounds(-45, shape.getBounds());
g2.draw(bottomRight);
if (mousePoint != null) {
if (bottomRight.contains(mousePoint)) {
g2.fill(bottomRight);
}
}
}
}
public Rectangle2D getActiveBounds(float angel, Rectangle bounds) {
Point2D p = getPointOnEdge(angel, bounds);
return new Rectangle2D.Double(p.getX() - 4, p.getY() - 4, 8, 8);
}
public Point2D getPointOnEdge(float angel, Rectangle bounds) {
float radius = Math.max(bounds.width, bounds.height) / 2;
float x = radius;
float y = radius;
double rads = Math.toRadians((angel + 90));
// Calculate the outter point of the line
float xPosy = (float) (x + Math.cos(rads) * radius);
float yPosy = (float) (y + Math.sin(rads) * radius);
return new Point2D.Float(xPosy + bounds.x, yPosy + bounds.y);
}
class MyMouseAdapter extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
mousePoint = e.getPoint();
repaint();
}
}
}
}
This example does all the work within the paint method, because I wanted to see the "area of effect", you can easily use the same logic to change the mouse cursor within the MouseMoitionListener
Not sure if this will work but you can try something like:
Create a Shape circle that is a couple of pixels smaller than your original Shape
Create a Shape circle that is a couple of pixels larger than your original Shape
Create an Area object using the larger Shape
Create an Area object using the smaller Shape and subtract this Area from the larger Area
Use the contains(...) method to determine if the mouse point is within this Area.
I have made a GUI that uses a slider to scale an object up and down.(in this case a rectangle). I was wondering if there was a way to also use a slider to specify a degree of rotation. So there would be 2 sliders one to control scale and another to control the rotation. If anyone could help me make this that would be great here is what I have so far with just the scale slider.
import javax.swing.*;
public class Parker
{
public static void main(String[] args)
{
TheWindow w = new TheWindow();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
w.setSize(1280,720);
w.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TheWindow extends JFrame
{
private JSlider slider; //declare slider
private drawRect myPanel; //declare/ create panel
public TheWindow()
{
super("Slider Example"); //make title
myPanel = new drawRect();
myPanel.setBackground(Color.cyan); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener
(
new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
add(myPanel, BorderLayout.CENTER);
}
import java.awt.*;
import javax.swing.*;
public class drawRect extends JPanel
{
private int d = 20; //this determines the beginning size of the rect.
public void paintComponent(Graphics g)//paints obj on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
// ImageIcon i = new ImageIcon("A:\\Capture.png"); //location of Image
// i.paintIcon(this, g, d, d); //paints icon on screen
int originX = getWidth() / 2; //this is subtracting half of 'd' from the center point to scale it form the center
int originY = getHeight() / 2;
int x = originX - (d / 2);
int y = originY - (d / 2);
System.out.println(x + "x" + y);
g.fillRect(x, y, d, d); //paints rectangle on screen
//x , y, width, height
}
Okay, I've been playing around with this for a while I would normally use a AffineTransform for this, but it was giving me weird results I couldn't resolve...
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.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Parker {
public static void main(String[] args) {
new Parker();
}
public Parker() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ControlPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ControlPane extends JPanel {
private JSlider slider; //declare slider
private DrawPane myPanel;
public ControlPane() {
setLayout(new BorderLayout());
myPanel = new DrawPane();
myPanel.setBackground(Color.cyan); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 400, 100);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener(
new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
myPanel.setScale(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
JSlider rotate = new JSlider(SwingConstants.VERTICAL, 0, 720, 0);
rotate.setMajorTickSpacing(20); //will set tick marks every 10 pixels
rotate.setPaintTicks(true); //this actually paints the ticks on the screen
rotate.addChangeListener(
new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
JSlider slider = (JSlider) e.getSource();
myPanel.setAngle(slider.getValue());
}
}
);
add(slider, BorderLayout.WEST);
add(rotate, BorderLayout.EAST);
add(myPanel);
myPanel.setScale(400);
}
}
public class DrawPane extends JPanel {
private double scale = 1;
private double angle = 0;
private final int rectWidth = 20;
private final int rectHeight = 20;
#Override
protected void paintComponent(Graphics g)//paints obj on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
int originX = getWidth() / 2;
int originY = getHeight() / 2;
int xOffset = -(rectWidth / 2);
int yOffset = -(rectHeight / 2);
g.setColor(Color.BLACK);
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(originX, originY);
g2d.scale(scale, scale);
g2d.rotate(Math.toRadians(angle), 0, 0);
g2d.fill(new Rectangle2D.Double(xOffset, yOffset, rectWidth, rectHeight));
g2d.dispose();
g.setColor(Color.RED);
g.drawRect(originX + xOffset, originY + yOffset, rectWidth, rectWidth);
}
public void setAngle(double angle) {
this.angle = angle;
repaint();
}
public void setScale(int scale) {
// Scaling is normalized so that 1 = 100%
this.scale = (scale / 100d);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Basically this uses the Graphics APIs capabilities, for simplicity (in particular with the spinning), the Graphics context is translated to the origin point. The rectangle is then paint around this origin point to allow it to be zoomed and rotate about it's center